Another question shows how to do a union in SQLAlchemy.
Is it possible to perform a union in SQLAlchemy without using a subquery?
For example, in the linked question SQLAlchemy produces SQL of the form:
SELECT * FROM (SELECT column_a FROM table_a UNION SELECT column_b FROM table_b)
But I would like SQLAlchemy to produce SQL like:
SELECT column_a FROM table_a UNION SELECT column_b FROM table_b
The latter SQL is shorter, doesn't use a subquery, and does the same thing. Can SQLAlchemy produces a union like the latter query?
Per the SQLAlchemy SQL Expression Language Tutorial:
You can use sqlalchemy.sql.expression.union:
from sqlalchemy.sql import union
u = union(
addresses.select().where(addresses.c.email_address == 'foo#bar.com'),
addresses.select().where(addresses.c.email_address.like('%#yahoo.com')),
).order_by(addresses.c.email_address)
u.compile()
This produces:
SELECT
addresses.id,
addresses.user_id,
addresses.email_address
FROM addresses WHERE addresses.email_address = ?
UNION
SELECT
addresses.id,
addresses.user_id,
addresses.email_address
FROM addresses
WHERE addresses.email_address LIKE ?
ORDER BY addresses.email_address
Params: ('foo#bar.com', '%#yahoo.com')
Related
I have 3 data to be searched in the database.
I need the 3 results to be visible, and the one that has made return null in the query.
I'm using union all to perform the duplicate search, this works.
The question is. I need to get all the data from the survey, even though it's null.
Could anyone get help?
thank you very much for your attention
select * from estoques where `si_id` = '02.352' union all select * from estoques where `si_id` = '05.173' union all select * from estoques where `si_id` = '02.305' order by `validade` asc
In this example the id 05.173 does not exist in the database.
Expected outcome
[
{siaId:'02.352', ...},
{null},
{siaId:'02.305', ...}
]
You can use a left join against a derived table:
SELECT b.*
FROM (
SELECT '02.352' AS si_id
UNION ALL
SELECT ...
) AS a
LEFT JOIN estoques AS b
USING (si_id)
ORDER BY a.si_id;
You may want to include the id in the output to be able to identify missing rows:
SELECT a.si_id, b.*
FROM ...
I have written a simple SQL query which looks like this:
Select * from tableName where tableId IN (id1,id2,id3....idN)
The query works just fine. My question is: Is there any quick way to find out which of the id[1-N] were NOT found in the result set? I know I can iterate through the result of the query and compare it with the IDs I passed in the query, but I hope there is a quicker way than that.
You could use a left join base
select id from (
select id1 id
union
select id2
union
select id3
....
union
select idN
) t
left join tableName a on a.tableId = t.id
where a.tableId is null
(if the values for id1 ... idN is a result for a subquery you could use the subquery instead of select union)
The inner query in the following SQL statement is to normalize part of the database (code1, code2, code3, etc.) With the outer query I want to select the codes that aren't in the lookup table (tblicd)
select primarycode from
(
select id, primarycode from myTable
union
select id, secondarycode from myTable
union
select id, tertiarycode from myTable) as t
order by id
where primarycode not in tblicd.icd_id
The query above doesn't run, I'm wondering what I'm doing wrong. The error I get is the multi-part identifier tblicd.icd_id could not be bound
One problem is your ORDER BY and WHERE clauses are reversed. The ORDER BY clause must come after the WHERE clause.
Your WHERE clause is also incorrect. It should be like this:
WHERE primarycode NOT IN (SELECT icd_id FROM tblicd)
ORDER BY id
where primarycode not in tblicd.icd_id
might be
where primarycode not in (SELECT icd_id FROM tblicd )
if select * from table where x=1 returns 0 rows, then I need select * from table where x=2 [or some other query]. Is it possible to do this in a single MySQL query with a conditional statement?
Edit: All answers with UNION work, but only if both queries select from the same table (or tables with the same number of columns). What if the second query is applied on a different table with joins?
Let me write down the my queries to make the question more clear:
1st:
SELECT table1.a, table2.b from table1 LEFT JOIN table2 ON table2.x= table1.x
WHERE .....
if the result from the 1st one is null then:
2nd:
SELECT table1.a FROM table1
WHERE ....
I will be using the rows from the 1st query if it returns any, otherwise the 2nd one will be used.
This appears to work from a quick test I just did and avoids the need to check for the existence of x=1 twice.
SELECT SQL_CALC_FOUND_ROWS *
FROM mytable
WHERE x = 1
UNION ALL
SELECT *
FROM mytable
WHERE
FOUND_ROWS() = 0 AND x = 2;
Edit: Following your clarification to the question obviously the 2 queries will need to be UNION compatible for the above to work.
The answer to your updated question is No. This is not possible in a single query. You would need to use some conditional procedural logic to execute the desired query.
You could try...
SELECT *
FROM mytable
WHERE x = 1
UNION
SELECT *
FROM mytable
WHERE x = 2 AND
NOT EXISTS (SELECT *
FROM mytable
WHERE x = 1);
if you don't consider it too ghastly a hack.
yes
Subqueries with EXISTS or NOT EXISTS
http://dev.mysql.com/doc/refman/5.1/en/exists-and-not-exists-subqueries.html
example :
SELECT column1 FROM t1 WHERE NOT EXISTS (SELECT * FROM t2);
If the two queries return different number of columns, you can pad one of the results with empty columns and also add an identifier column first.
SELECT SQL_CALC_FOUND_ROWS 1 query_type, mytable.*,
'' col1, '' col2, '' col3, '' col4
FROM mytable
WHERE x = 1
UNION ALL
SELECT 2, mytable2.*
FROM mytable2
WHERE
FOUND_ROWS() = 0 AND x = 2;
Where mytable2 has 4 more columns than mytable.
The simplest explanation is that:
SELECT IF(1 = 2,'true','false'); --> false
SELECT IF(1 = 1,' true','false'); --> true
SELECT IF(1 = 2,' true','false'), IF(1 = 1,' true','false'); --> false | true
The 'if' statement give some functionality to selected values.
The structure is something like this:
SELECT IF(<your statement>), ...<selected params>... FROM <your tables>
A great explanation can be found here.
SQL_CALC_FOUND_ROWS and FOUND_ROWS cannot be used in a single query, even if separate by UNION statements.
The correct way to do this would be:
WITH my_cte AS
(
SELECT * from original_set
)
SELECT * FROM my_cte
UNION ALL
SELECT opt.* FROM optional_set opt JOIN (SELECT count(*) v FROM my_cte) count ON count.v=0;
With the JOIN and the UNION ALL the performance of this query is almost equivalent to either of the individual standalone queries
you can use EXIST and NOT EXIST statement to check that result is null or not. if result is Null then you can get value from table2.
I have a "server" table which has a column named 'SN' in mysql, when do query to retrive servers with some sns from 'sn1' to 'sn10000', we can:
select * from server where sn in ('sn1','sn2','sn3',...'sn10000');
If there is only one sn in 'sn1'-'sn10000' which not exists in database, then the query above will retrive 9999 rows of result.
The question is how can I easily get which one in 'sn1'-'sn10000' is not exists in database except the additional work, such as handling the result with shell script etc.
I have an ugly sql like below can use:
select * from (select 'sn1' as sn
union select 'sn2'
union select 'sn3'
....
union select 'sn10000') as SN
where not exists (select id from server where server.sn=SN.sn);
Is Anyone has other better methods? Thanks.
Your query is perfectly fine for the intended use, but on MySQL the NOT IN and LEFT JOIN/IS NULL are more effecient that NOT EXISTS. Here are your alternatives:
NOT IN
SELECT *
FROM ( SELECT 'sn1' as sn
UNION ALL SELECT 'sn2'
UNION ALL SELECT 'sn3'
....
UNION ALL SELECT 'sn10000') as SN
WHERE sn.sn NOT IN (SELECT s.id FROM SERVER s)
LEFT JOIN/IS NULL
SELECT s.id
FROM SERVER s
LEFT JOIN ( SELECT 'sn1' as sn
UNION ALL SELECT 'sn2'
UNION ALL SELECT 'sn3'
....
UNION ALL SELECT 'sn10000') as SN ON SN.sn = s.id
WHERE sn.sn IS NULL
You might notice I used UNION ALL, rather than UNION - UNION removes duplicates (which won't happen in your example), making it slower so UNION ALL is a better choice.
Stick your sn1, sn2, sn3... sn10000 values in a temporary table, and then use Joins.
Select server.* from server inner join tempt on (tempt.value = server.sn)
will give you the ones that match, where as
Select sn.* from server right outer join tempt on (tempt.value = server.sn)
where server.somefield is Null
should take care of finding the missing ones.