How to find IDs that do not have data from another table - mysql

I am trying to write a query that will pull up IDs that do not have certain data in their table. Currently, we are trying to find people that belong in a certain table but are missing data.
For example, we want to make sure everyone has all three of these items
Table1
item_ID
item_1
item_2
item_3
And we have this below table
Table2
ID .. item_ID
1 .. item_1
1 .. item_2
1 .. item_3
2 .. item_1
2 .. item_2
3 .. item_1
And so on. You can see that ID 2 is missing item_3 from their table, and I want to pull a tuple that displays 2, item_3 in a query.
So far, I have something like this
SELECT DISTINCT b.ID, a.item
FROM TABLE1 a
LEFT OUTER JOIN TABLE2 b
ON a.ITEM_ID=b.ITEM_ID
WHERE b.ITEM_ID is NULL
I've been trying to write something where I can pull the item_IDs some IDs are missing, but nothing has worked so far.

SELECT a.ID, b.item_id
FROM (SELECT DISTINCT ID FROM Table2) AS a
-- or TableX AS a -- if you have a TableX with the unique ID values used for Table2
CROSS JOIN Table1 AS b
-- or (SELECT DISTINCT item_id FROM Table2) AS b -- if Table1 was not available
LEFT JOIN Table2 AS c ON a.ID = c.ID AND b.item_id = c.item_id
WHERE c.ID IS NULL
;

If you have a full list of IDs in table2 then you can use that but if you don't, you can use this:
SELECT ft.*
FROM TABLE2 t2 RIGHT OUTER JOIN
(SELECT b.ID, a.ITEM_ID
FROM TABLE1 a
CROSS JOIN (SELECT DISTINCT ID FROM TABLE2) b) ft
ON t2.id = ft.id AND t2.item_id = ft.item_id
WHERE t2.id IS NULL
http://sqlfiddle.com/#!9/2d0a19/7
I do a CROSS JOIN to get a list of what all the possible combinations should be and then choose the missing ones from the table.

Related

SQL JOIN and count without counting an ID twice

I am trying to join a table and get a count but I cannot count an ID twice in the table for the count.
Table 1:
ID animal
-- ------
1 dog
2 dog
3 cat
4 cat
5 dog
Table 2:
ID
--
2
2
3
5
5
I need to get a count of how many of each type of animal are in table 2. I can get it to join and change the ID to the type of animal and then get a count of each.
The issue is that each ID can only get counted once. So the expected output would be.
dog:2
cat:1
Where my output is
dog:4
cat:1
Try like below
select t1.animal, count( distinct t2.ID)
from table1 t1 join table2 t2 on t1.ID=t2.ID
group by t1.animal
You can try below using count distinct id
select b.animal,count(distinct a.id) from table2 a
inner join table1 b on a.id=b.id
group by b.animal
Try this:
SELECT t1.animal AS "Animal", COUNT(DISTINCT t1.ID) AS "No. of Animals"
FROM TABLE2 t2, TABLE1 t1
WHERE t2.ID = t1.ID
GROUP BY t1.animal
You can Try Nested Selects here.
SELECT
t.animal,
COUNT(t.ID) AS Count
FROM
(SELECT DISTINCT a.animal, b.ID FROM table1 a INNER JOIN table2 b ON a.ID = b.ID)t
GROUP BY t.animal
this is tested image

Returning ids of a table where all values of other table exist with this id using all() or exists()

I have three tables with following data
Table 3 :
Table1_id Table2_id
1 1
1 2
1 3
2 1
2 3
3 2
Table 2 :
Table2_id Name
1 A
2 B
3 C
Table 1 :
Table1_id Name
1 P
2 Q
3 R
I have a problem where I need to return all table1_id's which have an entry for all Table2_ids's in Table 3.
ie. I want my output to be
Table1_id
1
I found a solution using count().
But is there a way to use all() or exists() to solve the query?
Using NOT IN with excluding LEFT JOIN in a subselect with a CROSS JOIN
select *
from table1
where Table1_id not in (
select t1.Table1_id
from table1 t1
cross join table2 t2
left join table3 t3 using (Table1_id, Table2_id)
where t3.Table1_id is null
)
VS using COUNT()
select table1_id
from table3
group by table1_id
having count(1) = (select count(1) from table2)
Explanation:
The CROSS JOIN
select t1.Table1_id
from table1 t1
cross join table2 t2
represents how table3 would look like, if every item from table1 would be related to every item from table2.
A (natural) left join with table3 will show us which relations really exists. Filtering by where t3.Table1_id is null (excluding LEFT JOIN) we get the missing relations. Using that result for the NOT IN clause, we get only table1 items that have no missing relation with table2.
You can use the following query:
SELECT DISTINCT t1.*
FROM Table2 AS t2
CROSS JOIN Table1 AS t1
WHERE NOT EXISTS (SELECT 1
FROM Table3 AS t3
WHERE t1.Table1_id = t3.Table1_id AND
t2.Table2_id = t3.Table2_id)
to get Table1 records not having a complete set of entries from Table2 in Table3. Then use NOT IN to get the expected result.
Here is a solution using EXISTS and INNER JOIN.
SELECT DISTINCT t3_out.Table1_id FROM Table3 t3_out
WHERE EXISTS( SELECT 1
FROM Table2 t2 INNER JOIN Table3 t3 ON t2.Table2_id = t3.Table2_id
WHERE t3.Table1_id = t3_out.Table1_id
HAVING COUNT(DISTINCT t2.Table2_id) = 3 )

Show tree result between two table related with comma

In MySQL my table1 is
ID name parent
1 one 0
2 two 1
3 three 1
and my table2 is
ID name parent
1 com 2,3 -->is table1.ID
I want to relate between table2.parent and table1.id
and show tree result :
com -> one -> two,three
How can I query it?
I query this:
SELECT *
from table1 a
left join table1 b on b.parent=a.ID
where b.ID in (2,3)
this work nice
but didn't work this:
SELECT *
from table1 a
left join table1 b on b.parent=a.ID
where b.ID in (select parent from table2)
try this:
select *
from table2 t2
left join table1 t1 on find_in_set(t1.id, t2.parent) > 0
group by t2.id
;

Outer Join on multiple tables

select table3.tid, table3.name, talble4.name1, table4.name2 from table3 left join
(select table1.tid, table1.name as name1, table2.name as name2 from table1 left join table2
on table1.tid = table2.tid
union
select table2.tid, table1.name, table2.name from table1 right join table2
on table1.tid = table2.tid) as table4;
Please tell me what is wrong here.
I want a full outer join of the 3 tables : table1, table2 and table3 (which MYSQL does not support)
I would emulate a "full outer join" of three tables with three separate queries, with the rows concatenated together with UNION ALL operations.
The first query is all the tid values from table1. The second query gets all the tid values from table2 which don't exist in table1. The third query gets all the tid values in table3 which don't exist in table1 and don't exist in table2. The "trick" in the second and third queries is including appropriate
tid IS NULL
predicates in the WHERE clause, to make sure the tid values returned from the prior queries are omitted. (If we aren't guaranteed that tid is NOT NULL, we would probably want to avoid returning NULL values for tid by including an appropriate tid IS NOT NULL predicate in each of the queries for the "driving" table, which in the example below is the table following the FROM keyword.)
The last step is to include the name columns in the select list. For consistency, I'd put the name value from table1 in the same column. (In the second query, the name1 column will always be NULL, in the third query, the name1 and name2 columns will always be NULL.)
SELECT a.tid
, a.name AS name1
, b.name AS name2
, c.name AS name3
FROM table1 a
LEFT
JOIN table2 b ON b.tid = a.tid
LEFT
JOIN table3 c ON c.tid = a.tid
UNION ALL
SELECT d.tid
, f.name AS name1
, d.name AS name2
, e.name AS name3
FROM table2 d
LEFT
JOIN table3 e ON e.tid = d.tid
LEFT
JOIN table1 f ON f.tid = d.tid
WHERE f.tid IS NULL
UNION ALL
SELECT g.tid
, h.name AS name1
, i.name AS name2
, g.name AS name3
FROM table3 g
LEFT
JOIN table1 h ON h.tid = g.tid
LEFT
JOIN table2 i ON i.tid = g.tid
WHERE h.tid IS NULL
AND i.tid IS NULL
Hi you don't seem to have an "on table3.JoinColumn = table4.JoinColumn" after table4 in your SQL. I think you've been marked down as you didn't say what your error is, and I think your question is a little vague. But perhaps the SQL I've given may be all your need to complete your task...

LEFT JOIN 2 Table but will only return the 1st Record from Table2

table1
cid
itemdesc
itemprice
table2
cid
imagename
status
My 1st table is has unique cid (no duplicate) I want it to LEFT JOIN TO table2 but it has multiple rows per cid
cid imagename status
1 image1-of-cid1 test1
1 image2-of-cid1 test2
2 image1-of-cid2 test3
2 image2-of-cid2 test4
2 image3-of-cid2 test5
But I only want the Query to return the the 1st row only of the each record fom table 1
Thanks
I agree with John Woo's answer above. You need a subquery of some kind to actually retrieve the first row of table 2. Something like:
SELECT
t1.[id],
t2.*
FROM table1 AS t1
LEFT JOIN table2 AS t2
ON t2.cid = (SELECT TOP 1 cid FROM table2 WHERE cid = t1.cid)
you need to create an extra subquery that gets one imagename per cid. try this,
SELECT a.*, b.*
FROM table1 a
LEFT JOIN
(
SELECT cid, MIN(imagename) minImage
FROM table2
GROUP BY cid
) c ON a.cid = c.cid
LEFT JOIN table2 b
ON c.cid = b.cid AND
b.imageName = c.minImage
SQLFiddle Demo
Select
distinct a.cid,a.itemdesc,b.imagename,a.itemprice,b.status
from table1 a,
table2 b
where a.cid=b.cid
Try this:
SELECT a.cid, a.itemdesc, a.itemprice, b.imagename, b.status
FROM table1 a
LEFT OUTER JOIN table2 AS b ON a.cid = b.cid
GROUP BY a.cid, a.itemdesc, a.itemprice;