I'd like to perform a MySQL query such that:
SELECT * FROM table_A JOIN table_B on table_A.id = table_B.foreign_key
…but I'd like to return rows where there is no match in table_B for table_A. Is this possible? How can I accomplish it?
You want to use a LEFT OUTER JOIN and then a WHERE clause to only allow NULL on the joined table.
SELECT * FROM table_A
LEFT OUTER JOIN table_B ON table_A.id = table_B.foreign_key
WHERE table_B.foreign_key IS NULL
Try this:
SELECT *
FROM table_A
LEFT JOIN table_B on table_A.id = table_B.foreign_key
WHERE table_B.foreign_key IS NULL
Related
I would like to create equivalent MySQL query using LEFT OUTER JOIN to WHERE EXISTS. I am following this question:
Are the SQL concepts LEFT OUTER JOIN and WHERE NOT EXISTS basically the same?
This is the original query:
SELECT *
FROM tableA
JOIN tableB ON tableA.tableA_id = tableB.tableB_id
JOIN tableC ON tableC.tableC_id = tableB.tableB_id
WHERE NOT EXISTS (
SELECT 1
FROM tableD
WHERE tableA.employee_id = tableD.employee_id AND tableC.tableC_datum = DATE(tableD.tableD_od_datetime)
)
But this query return different values:
SELECT *
FROM tableA
JOIN tableB ON tableA.tableA_id = tableB.tableB_id
JOIN tableC ON tableC.tableC_id = tableB.tableB_id
LEFT OUTER JOIN tableD ON tableA.employee_id = tableD.employee_id AND tableC.tableC_datum = DATE(tableD.tableD_od_datetime)
WHERE tableD.employee_id IS NULL AND DATE(tableD.tableD_od_datetime) IS NULL
Why are these two outputs not equivalent, please?
The not exists and left join ... rgt.col is null approaches are identical. The left join however will contain columns from the unwanted table so just be specific with the select clause:
SELECT table_a.*, table_b.*, table_c.*
FROM table_a
JOIN table_b ...
JOIN table_c ...
LEFT JOIN table_d ...
I would rather avoid * at all and explicitly list exactly those columns that I need.
I want to join 2 tables and for each joined result I need a separate row, but the rows of my query result are somehow mixed:
Schema + Data:
My Query:
SELECT Table_A.id,
Table_B.id,
Table_C.id
FROM Table_A
LEFT JOIN Table_B
ON Table_B.id_a = Table_A.id
LEFT JOIN Table_C
ON Table_C.id_a = Table_A.id
The Result:
What I want (3 separate rows - separated by the join-tables' id-column):
Q: What am I doing wrong?
=> You could put it in that way: I need all rows of where id_a is 1 + table_a.id=1. Maybe JOIN is the wrong approach here..?
You need INNER JOIN UNION :
SELECT A.id A_Id, B.id B_Id, ''c_id
FROM Table_A A
INNER JOIN Table_B B ON B.id_a = A.id
UNION ALL
SELECT A.id A_Id, '' B_Id, c.id c_id
FROM Table_A A
INNER JOIN Table_C C ON A.id = C.id_a
table_a contains all orders, while table_b contains only special orders. Every order in each table has a code_field. All orders in table_b are also in table_a, but of course not all orders in table_a are also in table_b. I need to extract all orders in table_a that are not also in table_b. Looking for a solution but I actually cannot figure out how to write it.
You can select everything from table_a and left join table_b by code_field and wherever you don't have matching order in table_b the fields will be null
SELECT table_a.*
FROM table_a
LEFT JOIN table_b
ON table_a.code_field = table_b.code_field
AND table_b.id IS NULL
You can do it with NOT EXISTS:
SELECT *
FROM table_a
WHERE NOT EXISTS (
SELECT 1 FROM table_b
WHERE table_a.code_field = table_b.code_field
)
I'd like to bring in just the most recent date row along with other fields from Table B that would include all values for multiple columns in Table A, even if there is no value in Table B.
The following query works, but only returns values that exist in both Table A AND in Table B. How do I include all of A and the most recent date row of B?
Many Thanks!
SELECT A.person_id,
A.second_field,
B.create_timestamp,
B.second_field
FROM (
SELECT B.person_id, max(B.create_timestamp) as create_timestamp
FROM Table_B B
GROUP BY B.person_id
) BMaxDate
LEFT JOIN Table_B B
ON BMaxDate.person_id = B.person_id AND
BMaxDate.create_timestamp = B.create_timestamp
LEFT JOIN Table_A A ON BMaxDate.person_id = A.person_id
You have to use Table_A as the first table in the LEFT JOIN operation chain:
SELECT A.person_id,
A.second_field,
B.create_timestamp,
B.second_field
FROM Table_A AS A
LEFT JOIN (
SELECT B.person_id, max(B.create_timestamp) as create_timestamp
FROM Table_B B
GROUP BY B.person_id
) AS BMaxDate ON BMaxDate.person_id = A.person_id
LEFT JOIN Table_B AS B
ON BMaxDate.person_id = B.person_id AND
BMaxDate.create_timestamp = B.create_timestamp
If you want all from table_A and use a left join you have to put table_A first.
And for Sql Server you can use the with clause for more readable sub query. Mysql doesn't support the with clause.
With(
SELECT B.person_id, max(B.create_timestamp) as create_timestamp
FROM Table_B B
GROUP BY B.person_id
) AS BMaxDate
SELECT A.person_id,
A.second_field,
B.create_timestamp,
B.second_field
FROM Table_A AS A
LEFT JOIN BMaxDate ON BMaxDate.person_id = A.person_id
LEFT JOIN Table_B AS B ON BMaxDate.person_id = B.person_id
AND BMaxDate.create_timestamp = B.create_timestamp
SELECT * FROM
Table_A
LEFT JOIN Table_B
ON (Table_A.A_ID = Table_B.A_ID)
INNER JOIN Table_C ON (Table_C.C_ID = Table_B.C_ID)
WHERE Table_A.ID = 3
This returns 0 rows, currently.
How can I set this up so I always get Table_A, even if there is no row for Table_B or Table_C. I still want to maintain the INNER JOIN between Table_B and Table_C, so that I will never get a B without a C.
Sub query the Table B and Table C. e.g.
SELECT *
FROM Table_A
LEFT JOIN
(SELECT *
FROM Table_B
INNER JOIN Table_C ON (Table_C.C_ID = Table_B.C_ID)
) B_AND_C ON (Table_A.A_ID = B_AND_C.A_ID)
WHERE Table_A.ID = 3
You may not have to use an inline view. I'm not in front of a machine with MySQL right now so I can't check but you can try
SELECT *
FROM table_A a
LEFT JOIN (table_B b
INNER JOIN table_C c
ON b.c_id = c.c_id)
ON a.b_id = b.b_id
WHERE
a.a_id =3