i have for example:
tableAaa:
id | titleSSS
1 | sfdf
2 | sdfs
tableBbb:
id | titleUUU
1 | sfdf
2 | sdfs
tableCcc:
id | titleIII
1 | sfdf
2 | sdfs
etc, for example * 10.
Is possible make something like:
SELECT title* FROM table*
If yes, how?
EDIT: i dont want use UNION and do select from each table... These table is ~100. I would like make regular expression.
You can do it, but you'll have to list all column and table names manually:
SELECT titleSSS FROM tableAaa
UNION ALL
SELECT titleUUU FROM tableBbb
UNION ALL
SELECT titleIII FROM tableCcc
Note that you must use UNION ALL instead of UNION or otherwise you won't get duplicate rows in the output. Read more here: http://dev.mysql.com/doc/refman/5.0/en/union.html
The thing require by you is might not be possible you can do as below
SELECT title1 FROM table1
union
SELECT title2 FROM table2
union
SELECT title3 FROM table3
OR
You can make use of DynamicSQL to resolve your issue easily.
ans for you : How To have Dynamic SQL in MySQL Stored Procedure
Related
I have two tables (Table A and Table B).
These have different number of columns - Say Table A has more columns.
How can I union these two table and get null for the columns that Table B does not have?
Add extra columns as null for the table having less columns like
Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2
I came here and followed above answer. But mismatch in the Order of data type caused an error. The below description from another answer will come handy.
Are the results above the same as the sequence of columns in your table? because oracle is strict in column orders. this example below produces an error:
create table test1_1790 (
col_a varchar2(30),
col_b number,
col_c date);
create table test2_1790 (
col_a varchar2(30),
col_c date,
col_b number);
select * from test1_1790
union all
select * from test2_1790;
ORA-01790: expression must have same datatype as corresponding expression
As you see the root cause of the error is in the mismatching column ordering that is implied by the use of * as column list specifier. This type of errors can be easily avoided by entering the column list explicitly:
select col_a, col_b, col_c from test1_1790
union all
select col_a, col_b, col_c from test2_1790;
A more frequent scenario for this error is when you inadvertently swap (or shift) two or more columns in the SELECT list:
select col_a, col_b, col_c from test1_1790
union all
select col_a, col_c, col_b from test2_1790;
OR if the above does not solve your problem, how about creating an ALIAS in the columns like this: (the query is not the same as yours but the point here is how to add alias in the column.)
SELECT id_table_a,
desc_table_a,
table_b.id_user as iUserID,
table_c.field as iField
UNION
SELECT id_table_a,
desc_table_a,
table_c.id_user as iUserID,
table_c.field as iField
Normally you need to have the same number of columns when you're using set based operators so Kangkan's answer is correct.
SAS SQL has specific operator to handle that scenario:
SAS(R) 9.3 SQL Procedure User's Guide
CORRESPONDING (CORR) Keyword
The CORRESPONDING keyword is used only when a set operator is specified. CORR causes PROC SQL to match the columns in table expressions by name and not by ordinal position. Columns that do not match by name are excluded from the result table, except for the OUTER UNION operator.
SELECT * FROM tabA
OUTER UNION CORR
SELECT * FROM tabB;
For:
+---+---+
| a | b |
+---+---+
| 1 | X |
| 2 | Y |
+---+---+
OUTER UNION CORR
+---+---+
| b | d |
+---+---+
| U | 1 |
+---+---+
<=>
+----+----+---+
| a | b | d |
+----+----+---+
| 1 | X | |
| 2 | Y | |
| | U | 1 |
+----+----+---+
U-SQL supports similar concept:
OUTER UNION BY NAME ON (*)
OUTER
requires the BY NAME clause and the ON list. As opposed to the other set expressions, the output schema of the OUTER UNION includes both the matching columns and the non-matching columns from both sides. This creates a situation where each row coming from one of the sides has "missing columns" that are present only on the other side. For such columns, default values are supplied for the "missing cells". The default values are null for nullable types and the .Net default value for the non-nullable types (e.g., 0 for int).
BY NAME
is required when used with OUTER. The clause indicates that the union is matching up values not based on position but by name of the columns. If the BY NAME clause is not specified, the matching is done positionally.
If the ON clause includes the “*” symbol (it may be specified as the last or the only member of the list), then extra name matches beyond those in the ON clause are allowed, and the result’s columns include all matching columns in the order they are present in the left argument.
And code:
#result =
SELECT * FROM #left
OUTER UNION BY NAME ON (*)
SELECT * FROM #right;
EDIT:
The concept of outer union is supported by KQL:
kind:
inner - The result has the subset of columns that are common to all of the input tables.
outer - The result has all the columns that occur in any of the inputs. Cells that were not defined by an input row are set to null.
Example:
let t1 = datatable(col1:long, col2:string)
[1, "a",
2, "b",
3, "c"];
let t2 = datatable(col3:long)
[1,3];
t1 | union kind=outer t2;
Output:
+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
| 1 | a | |
| 2 | b | |
| 3 | c | |
| | | 1 |
| | | 3 |
+------+------+------+
demo
if only 1 row, you can use join
Select t1.Col1, t1.Col2, t1.Col3, t2.Col4, t2.Col5 from Table1 t1 join Table2 t2;
I've got the following two tables (in MySQL):
Phone_book
+----+------+--------------+
| id | name | phone_number |
+----+------+--------------+
| 1 | John | 111111111111 |
+----+------+--------------+
| 2 | Jane | 222222222222 |
+----+------+--------------+
Call
+----+------+--------------+
| id | date | phone_number |
+----+------+--------------+
| 1 | 0945 | 111111111111 |
+----+------+--------------+
| 2 | 0950 | 222222222222 |
+----+------+--------------+
| 3 | 1045 | 333333333333 |
+----+------+--------------+
How do I find out which calls were made by people whose phone_number is not in the Phone_book? The desired output would be:
Call
+----+------+--------------+
| id | date | phone_number |
+----+------+--------------+
| 3 | 1045 | 333333333333 |
+----+------+--------------+
There's several different ways of doing this, with varying efficiency, depending on how good your query optimiser is, and the relative size of your two tables:
This is the shortest statement, and may be quickest if your phone book is very short:
SELECT *
FROM Call
WHERE phone_number NOT IN (SELECT phone_number FROM Phone_book)
alternatively (thanks to Alterlife)
SELECT *
FROM Call
WHERE NOT EXISTS
(SELECT *
FROM Phone_book
WHERE Phone_book.phone_number = Call.phone_number)
or (thanks to WOPR)
SELECT *
FROM Call
LEFT OUTER JOIN Phone_Book
ON (Call.phone_number = Phone_book.phone_number)
WHERE Phone_book.phone_number IS NULL
(ignoring that, as others have said, it's normally best to select just the columns you want, not '*')
SELECT Call.ID, Call.date, Call.phone_number
FROM Call
LEFT OUTER JOIN Phone_Book
ON (Call.phone_number=Phone_book.phone_number)
WHERE Phone_book.phone_number IS NULL
Should remove the subquery, allowing the query optimiser to work its magic.
Also, avoid "SELECT *" because it can break your code if someone alters the underlying tables or views (and it's inefficient).
The code below would be a bit more efficient than the answers presented above when dealing with larger datasets.
SELECT *
FROM Call
WHERE NOT EXISTS (
SELECT 'x'
FROM Phone_book
WHERE Phone_book.phone_number = Call.phone_number
);
SELECT DISTINCT Call.id
FROM Call
LEFT OUTER JOIN Phone_book USING (id)
WHERE Phone_book.id IS NULL
This will return the extra id-s that are missing in your Phone_book table.
I think
SELECT CALL.* FROM CALL LEFT JOIN Phone_book ON
CALL.id = Phone_book.id WHERE Phone_book.name IS NULL
SELECT t1.ColumnID,
CASE
WHEN NOT EXISTS( SELECT t2.FieldText
FROM Table t2
WHERE t2.ColumnID = t1.ColumnID)
THEN t1.FieldText
ELSE t2.FieldText
END FieldText
FROM Table1 t1, Table2 t2
SELECT name, phone_number FROM Call a
WHERE a.phone_number NOT IN (SELECT b.phone_number FROM Phone_book b)
Alternatively,
select id from call
minus
select id from phone_number
Don't forget to check your indexes!
If your tables are quite large you'll need to make sure the phone book has an index on the phone_number field. With large tables the database will most likely choose to scan both tables.
SELECT *
FROM Call
WHERE NOT EXISTS
(SELECT *
FROM Phone_book
WHERE Phone_book.phone_number = Call.phone_number)
You should create indexes both Phone_Book and Call containing the phone_number. If performance is becoming an issue try an lean index like this, with only the phone number:
The fewer fields the better since it will have to load it entirely. You'll need an index for both tables.
ALTER TABLE [dbo].Phone_Book ADD CONSTRAINT [IX_Unique_PhoneNumber] UNIQUE NONCLUSTERED
(
Phone_Number
)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = ON) ON [PRIMARY]
GO
If you look at the query plan it will look something like this and you can confirm your new index is actually being used. Note this is for SQL Server but should be similar for MySQL.
With the query I showed there's literally no other way for the database to produce a result other than scanning every record in both tables.
http://i.stack.imgur.com/ZRH9c.jpg (Please see Example Image of Database Structure)
Hi all,
I'm trying to search for words in two tables that Start with a specific Letter and I don't know how to do the proper join.
If there is NOT given a voc_id in "user_vocabulary" I want to take the word from user_vocabulary but if there is a voc_id I want to read all data from "system_vocabulary" WHERE user_vocabulary.voc_id=system.vocabulary.id .
This I use to just read one table (just for your information):
SELECT * FROM user_vocabulary WHERE word LIKE '$user_input%' ORDER BY word ASC
I've found some more or less similar posts but seem not to be able to convert those to this issue.
Any help is much appreciated.
cheers
Tom
You'll want values taken from user_vocabulary.word and system_vocabulary.word to end up in the same column in the output. You can do this with the IF function:
SELECT
uv.id,
IF(uv.voc_id = 0,uv.word,sv.word) AS WORD
FROM user_vocabulary uv
LEFT JOIN system_vocabulary sv
ON (uv.voc_id = sv.id)
HAVING word LIKE '%user_input%'
+------+-------+
| id | word |
+------+-------+
| 1 | hat |
| 2 | home |
| 3 | hello |
+------+-------+
3 rows in set (0.00 sec)
Try this
SELECT *
FROM user_vocabulary
left join system_vocabulary
on system_vocabulary.voc_id = user_vocabulary.id
WHERE user_vocabulary.word LIKE '%$user_input%' or system_vocabulary.word like '%$user_input%'
ORDER BY word ASC
EDITED
The other way
SELECT *
FROM user_vocabulary as uv
, system_vocabulary as sv
WHERE uv.word LIKE '%$user_input%'
or sv.word like '%$user_input%'
This should work according to your requirements:
SELECT user_vocabulary.id,
COALESCE(system_vocabulary.word, user_vocabulary.word) word
FROM user_vocabulary
LEFT JOIN system_vocabulary
ON system_vocabulary.id = voc_id AND voc_id <> 0
I have a MySQL query that runs a brief operation (totalling the counts in a select statement) and I want to use the result to do a math operation, but I'm getting an error.
Table:
id | group | count |
-----------------------------
1 1 3
2 1 2
Query:
select id, count,
(select sum(count) from table group by group) as total,
count/total as percent
from table
The error is because there is no real "total" column in the table. How can I make the query work?
You can save total as a variable, then use that in the division calculation.
SELECT
`id`, `count`,
#total:=(SELECT sum(`count`) FROM `table` GROUP BY `group`) AS `total`,
`count`/#total AS `percent`
FROM `table`
NOTE: GROUP is a reserved word in MySQL. You should enclose it (and all other field/table names) in backticks (`).
You can also do this without introducing a variable:
select id,
count,
(select sum(count) from `table` group by `group`) as total,
(select count/total) as percent
from `table`;
Produces:
+------+-------+-------+---------+
| id | count | total | percent |
+------+-------+-------+---------+
| 1 | 3 | 5 | 0.6000 |
| 2 | 2 | 5 | 0.4000 |
+------+-------+-------+---------+
2 rows in set (0.05 sec)
Your problem is that the inner query needs to generate 1 result per row, not 1 for every group. You want to add a where clause in the inner query saying something like
where inner_table.group = outer_table.group
so that only one result is returned.
group is a reserved word in mysql, as is table, you should use it like:
select id, count, (select sum(count) from `table` group by `group`) as total, count/total as percent from `table`
For more information: MySQL Reserved Words
You'll see there that you can actually use count but I would put all table and column names in quotes anyway.
This question already has an answer for MySql but by mistake if anyone lands here for MSSql as i did, it is as simple as below for MSSql
select id, count,
total = (select sum(count) from table group by group),
count/total as percent
from table
I am searching for records in a table as follows:
SELECT Id, Name FROM my_table WHERE Name LIKE '%prashant%' LIMIT 0, 10;
Now, I am adding LIMIT to maintain my paging. But when user searches for word 'prashant' then total records I have is 124 for 'prashant'. But as the limit applied to the query so it only fetches 10 records in my PHP script and when I am count the mysql variable in PHP code it returns total records found is 10.
So basically I want to count and Limit using a single query, by making some modification in the above query, I want the total count (124) of records. I don't want to run a separate count(*) query for just counting the total result found by the query.
Thanks.
SELECT SQL_CALC_FOUND_ROWS
Id, Name
FROM my_table
WHERE
Name LIKE '%prashant%'
LIMIT 0, 10;
# Find total rows
SELECT FOUND_ROWS();
more info
MySQL supports doing this using SQL_CALC_FOUND_ROWS as mentioned by Ionut. However, it turns out that in many cases it's actually faster to do it the old fashioned way using two statements, where one of them is a regular count(). This does however require that the counting can be done using an index scan, which won't be the case for this very query, but I thought I'd mention it anyway.
This is for others with the same need (considering it's been 3 years from the time of this question).
I had a similar issue and I didn't want to create 2 queries. So what I did was to create an additional column for the total number and moved the LIMIT and OFFSET clauses at the end:
SELECT SQL_CALC_FOUND_ROWS * FROM (
SELECT `id`, `name`
FROM `my_table`
WHERE `name` LIKE '%prashant%'
) res,
(SELECT /*CEIL(FOUND_ROWS()/10) AS 'pages',*/ FOUND_ROWS() AS 'total') tot
LIMIT 0, 10
So the result is something like
| id | name | total |
+-----+----------------+-------+
| 1 | Jason Prashant | 124 |
| 2 | Bob Prashant | 124 |
| 3 | Sam Prashant | 124 |
| 4 | etc. prashant | 124 |
and I think this solution has no disadvantage in timing because it fetches the result only once, and then uses the already calculated row count for the additional column.
In case of huge tables and selecting multiple fields (not just Id, Name as in your example) i would recommend to use 2 queries. Selecting count(0) first with all those WHERE clauses and only then build the pagination, selecting data etc.
It will work really faster on some popular eCommerce website, for example.
Don't use SQL_CALC_FOUND_ROWS and FOUND_ROWS()
there are the bugs reported
here: https://bugs.mysql.com/bug.php?id=18454
and here: https://bugs.mysql.com/bug.php?id=19553
while on small tables BENCHMARK is dependent more on other things and the resulting time your SELECT will take will be roughly the same as COUNT(0) - SQL_CALC_FOUND_ROWS still puts restraints on LIMIT and ORDER BY database optimizations so if you depend on them don't use SQL_CALC_FOUND_ROWS
on large tables the BENCHMARK difference becomes huge where a COUNT(0) might take 0.003 sec the same SQL_CALC_FOUND_ROWS might now take 20 sec
By all metrices COUNT(0) is the superior choice
COUNT(0) SYNTAX:
(SELECT COUNT(0) FROM tableNames WHERE condition) AS alias
// alias is optional but needed if you need to use the result later
So your total query would look like this
(SELECT COUNT(0) FROM my_table WHERE name LIKE '%prashant%') AS countResults;
SELECT Id, Name FROM my_table WHERE Name LIKE '%prashant%' LIMIT 0, 10;
And then just call countResults whereever you need it elsewhere...
Another advantage of using COUNT(0) is you can use it for searching both the same table as here or you can use it to search a different table...
So for instance if each person found also has 3, 2, 1, 5 diffenrent jobs respectively... you could just add a
(SELECT COUNT(0) FROM my_jobs_table WHERE name = name_row_in_jobs_table) AS jobs
inside your original SELECT like this
SELECT Id, Name (SELECT COUNT(0) FROM my_jobs_table WHERE name = name_row_in_jobs_table) AS jobs FROM my_table WHERE Name LIKE '%prashant%' LIMIT 0, 10;
Giving you:
--------------------
| id | Name | jobs |
--------------------
| 1 | Alice| 3 |
--------------------
| 2 | John | 2 |
--------------------
| 3 | Bob | 1 |
--------------------
| 4 | Jill | 5 |
--------------------
So when showing name[3] (ie. Bob) you could also show that Bob has 1 job by calling jobs[3]...