Improved way to find out "unused" values in SELECT WHERE IN statement - mysql

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)

Related

How to Sum with multitable

I want to do something like this:
SELECT SUM(qty)
FROM table1
WHERE colum1 LIKE (
SELECT colum2
FROM table2
WHERE condition2 LIKE 'value2'
)
It will work if the subquery returns a single row. When you use a subquery as an express, it must return a single value.
A more general method is to use a JOIN. This will sum the quantities of rows that match any of the selected colum2 values.
SELECT SUM(qty)
FROM (
SELECT DISTINCT id, qty
FROM table1
JOIN table2 ON table1.colum1 LIKE table2.colum2
WHERE table2.condition2 LIKE 'value2'
) x
You need the subquery with DISTINCT in case colum1 matches multiple patterns, so you don't sum the same quantity twice repeatedly for each match.
If value2 or table2.colum2 contains fixed strings rather than wildcard patterns, you should use = rather than LIKE.
You can make it work using
select Sum(column) from
Table1 where column IN
( Select column from TableName where
Condition);

Compare one table with another in mysql and display matched record

I have two mysql tabales.
Table1:opened_datatable
Table2:unidata
Table1 has only one column:Emails
Table2 has 45 columns, three of them are:Email_Office, Email_Personal1, Email_Personal2
I want to fetch full rows from Table2-unidata if Emails column of Table1 matches with either Email_Office or Email_Personal1 or Email_Personal2. I am getting little bit confused here.I tried this way:
select a.emails
from opened_datatable a
where a.Emails in (select *
from unidata b
where b.email_office=a.emails
or b.Email_Personal1=a.emails
or b.Email_Personal2=a.Emails
)
Its showing only one row of first table while I want to show matched rows of Table2 -unidata. First I need to mention table 2 and then I should have to match it with table 1-opened_datatable. But how can I do that?
Try This:
SELECT a.emails, b.*
FROM opened_datatable a
INNER JOIN unidata b ON a.emails IN (b.email_office, b.Email_Personal1, b.Email_Personal2)
Your current query should return an error.
Try a Corrrelated Subquery using EXISTS, quite similar to your apporach:
select a.emails
from opened_datatable a
where EXISTS
( select *
from unidata b
where b.email_office=a.emails
or b.Email_Personal1=a.emails
or b.Email_Personal2=a.Emails
)
You will probably not get good performance due to the OR-ed conditions.
Edit:
If performance is too bad, you might try a UNION approach:
select a.emails
from opened_datatable a
where a.emails
IN
( select email_office
from unidata b
UNION
select Email_Personal1
from unidata b
UNION
select b.Email_Personal2
from unidata b
)

Use GROUP_CONCAT result in IN Clause Mysql

I have a Query which returns comma separated integers
like :
select GROUP_CONCAT(ids) from table2
now I want to use that result in another query
like :
select * from table1 where column in (select GROUP_CONCAT(ids) from table2)
in this case it will consider only first value in IN clause.
I agree with #Alma that this can't be done with IN, you might be able to do it with FIND_IN_SET, but if you can do it with IN it's probably a better approach :
SELECT *
FROM table1
WHERE find_in_set(ids, (
SELECT GROUP_CONCAT(ids)
FROM table2
)) != 0;
sqlfiddle demo
Any special reason not using a join and using a sub query
select * from table1 t1
JOIN table2 t2 on (t2.column = t1.ids)

Combining results of multiple subqueries in one set

I am trying to exclude rows in my table based on the id's in other tables.
I have 2 tables of which a "select * from" results in a set like (1,2,3)
I am trying to combine the results from these 2 subqueries into one, like:
(1,2,3) + (4,5) = (1,2,3,4,5)
So I can filter the big table with a "NOT IN (1,2,3,4,5)"
I have been looking at GROUP_CONCAT's, UNION and all other kinds, but I can't seem to find something that actually works.
Anyone have a idea?
select *
from Table3
where id not in (
select id from Table1 --your subquery that returns 1,2,3
union all
select id from Table2 --your subquery that returns 4,5
)
select * from mytable
where id not in (
select id from othertable
union
select id from othertable2
)

MYSQL if a select query returns 0 rows then another select query?

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.