I have a question about using three joins between 3 tables. Changing the type of JOIN between second and third tables, the result changes and I don't understand why.
TABLE1 NAME AND AGE
NAME
AGE
BILL
20
JOHN
25
MARTHA
34
STEVE
40
EMILY
30
TABLE2 NAME AND ID
NAME
ID
BILL
001S
JOHN
002B
MARTHA
001Z
TABLE3 ID AND HOBBIES
ID
HOBBIES
001S
FOOTBALL
002B
MUSIC
001Z
VOLLEYBALL
EXAMPLE1
SELECT NAME, HOBBIES
FROM TABLE1
LEFT JOIN TABLE2 ON TABLE1.NAME = TABLE2.NAME
LEFT JOIN TABLE3 ON TABLE2.ID = TABLE3.ID
EXAMPLE2
SELECT NAME, HOBBIES
FROM TABLE1
LEFT JOIN TABLE2 ON TABLE1.NAME = TABLE2.NAME
INNER JOIN TABLE3 ON TABLE2.ID = TABLE3.ID
I want all the NAMES, no matter if they have HOBBIES or not. And this only happens in EXAMPLE1, in EXAMPLE2 the query returns the NAMES with HOBBIES, but I can't understand why it's not working with EXAMPLE2. The only difference is the INNER and that does not affect the relationship between table 1 and 2.
Where am I going wrong?
Since you used INNER JOIN in your latter join:
INNER JOIN TABLE3 ON TABLE2.ID = TABLE3.ID
This condition requires that the row include a non-NULL value for TABLE2.ID. This rules out any case where the join to TABLE2 produced no matches.
You can solve this by doing an outer join to the pairing of TABLE2 and TABLE3:
SELECT TABLE1.NAME, HOBBIES
FROM TABLE1
LEFT JOIN (TABLE2 INNER JOIN TABLE3 ON TABLE2.ID = TABLE3.ID)
ON TABLE1.NAME = TABLE2.NAME;
You can also solve it by using RIGHT OUTER JOIN:
SELECT TABLE1.NAME, HOBBIES
FROM TABLE2 INNER JOIN TABLE3 ON TABLE2.ID = TABLE3.ID
RIGHT OUTER JOIN TABLE1 ON TABLE1.NAME = TABLE2.NAME;
Related
I have these MySQL tables:
table1:
id | writer
1 | Bob
2 | Marley
3 | Michael
table2:
user_one | user_two
1 | 2
And this query:
SELECT table1.id FROM table1 LEFT JOIN table2 ON table1.id = table2.user_one
This query will return all rows of table1 which are 1,2,3
I want to select only rows which are not found in the left joint. So it should return only row with id 3
I want sort of the opposite of INNER JOIN which will select only the rows which are found in the join. How to get the opposite like if left join exists, ignore it and move to the next row. Hope i'm clear
You could use the following query:
SELECT table1.id
FROM table1
LEFT JOIN table2
ON table1.id IN (table2.user_one, table2.user_two)
WHERE table2.user_one IS NULL;
Although, depending on your indexes on table2 you may find that two joins performs better:
SELECT table1.id
FROM table1
LEFT JOIN table2 AS t1
ON table1.id = t1.user_one
LEFT JOIN table2 AS t2
ON table1.id = t2.user_two
WHERE t1.user_one IS NULL
AND t2.user_two IS NULL;
One of the best approach if you do not want to return any columns from table2 is to use the NOT EXISTS
SELECT table1.id
FROM table1 T1
WHERE
NOT EXISTS (SELECT *
FROM table2 T2
WHERE T1.id = T2.user_one
OR T1.id = T2.user_two)
Semantically this says what you want to query: Select every row where there is no matching record in the second table.
MySQL is optimized for EXISTS: It returns as soon as it finds the first matching record.
One more note to this:
When you check against a nullable column in the joined table, depending on your needs, you may have to use NOT EXISTS (or check against other columns when using LEFT JOIN), because MySQL won't be able to distinguish between a column which is NULL, but there is an existing record in the joined table and a column which is generated as NULL because the joined table have no matching record.
Here is a query that returns only the rows where no correspondance has been found in both columns user_one and user_two of table2:
SELECT T1.*
FROM table1 T1
LEFT OUTER JOIN table2 T2A ON T2A.user_one = T1.id
LEFT OUTER JOIN table2 T2B ON T2B.user_two = T1.id
WHERE T2A.user_one IS NULL
AND T2B.user_two IS NULL
There is one jointure for each column (user_one and user_two) and the query only returns rows that have no matching jointure.
Hope this will help you.
SELECT table1.id
FROM table1
LEFT JOIN table2 ON table1.id = table2.user_one
WHERE table2.user_one is NULL
Try following query:-
SELECT table1.id
FROM table1
where table1.id
NOT IN (SELECT user_one
FROM Table2
UNION
SELECT user_two
FROM Table2)
Hope this helps you.
Try:
SELECT A.id FROM
(
SELECT table1.id FROM table1
LEFT JOIN table2 ON table1.id = table2.user_one
WHERE table2.user_one IS NULL
) A
JOIN (
SELECT table1.id FROM table1
LEFT JOIN table2 ON table1.id = table2.user_two
WHERE table2.user_two IS NULL
) B
ON A.id = B.id
See Demo
Or you could use two LEFT JOINS with aliases like:
SELECT table1.id FROM table1
LEFT JOIN table2 A ON table1.id = A.user_one
LEFT JOIN table2 B ON table1.id = B.user_two
WHERE A.user_one IS NULL
AND B.user_two IS NULL
See 2nd Demo
Lets say I have 2 tables:
table1
table1_id
table1_name
table2
table2_id
table2_name
table2_description
table1_id
I join like so:
SELECT * FROM table1 LEFT JOIN table2 ON table1.table1_id = table2.table1_id
How can I have table1_id return its default value instead of NULL when there are no matches in table2?
Answer: Since table1_id exists in both tables, I needed to used aliases.
SELECT *, table1.table1_id AS tid, table2.table1_id AS t2id FROM table1 LEFT JOIN table2 ON table1.table1_id = table2.table1_id
If I understand correctly, you bring in the default row and then use logic in the select:
SELECT t1.*,
COALESCE(t2.table2_name, t2def.table2_name) as table2_name,
. . .
FROM table1 t1 LEFT JOIN
table2 t2
ON t1.table1_id = t2.table1_id LEFT JOIN
table2 t2def
ON t2def.table1_id = $defaultid;
SELECT table1.*
table2.table2_id,
table2.table2_name,
table2.table2_description,
ifnull(table2.table1_id, table1.table1_id) t2id
FROM table1 LEFT JOIN table2
ON table1.table1_id = table2.table1_id
Again, there is no point to check if table2.table1_id is null, as it is the join column ... always either NULL or exactly same as table1.table1_id
I have these MySQL tables:
table1:
id | writer
1 | Bob
2 | Marley
3 | Michael
table2:
user_one | user_two
1 | 2
And this query:
SELECT table1.id FROM table1 LEFT JOIN table2 ON table1.id = table2.user_one
This query will return all rows of table1 which are 1,2,3
I want to select only rows which are not found in the left joint. So it should return only row with id 3
I want sort of the opposite of INNER JOIN which will select only the rows which are found in the join. How to get the opposite like if left join exists, ignore it and move to the next row. Hope i'm clear
You could use the following query:
SELECT table1.id
FROM table1
LEFT JOIN table2
ON table1.id IN (table2.user_one, table2.user_two)
WHERE table2.user_one IS NULL;
Although, depending on your indexes on table2 you may find that two joins performs better:
SELECT table1.id
FROM table1
LEFT JOIN table2 AS t1
ON table1.id = t1.user_one
LEFT JOIN table2 AS t2
ON table1.id = t2.user_two
WHERE t1.user_one IS NULL
AND t2.user_two IS NULL;
One of the best approach if you do not want to return any columns from table2 is to use the NOT EXISTS
SELECT table1.id
FROM table1 T1
WHERE
NOT EXISTS (SELECT *
FROM table2 T2
WHERE T1.id = T2.user_one
OR T1.id = T2.user_two)
Semantically this says what you want to query: Select every row where there is no matching record in the second table.
MySQL is optimized for EXISTS: It returns as soon as it finds the first matching record.
One more note to this:
When you check against a nullable column in the joined table, depending on your needs, you may have to use NOT EXISTS (or check against other columns when using LEFT JOIN), because MySQL won't be able to distinguish between a column which is NULL, but there is an existing record in the joined table and a column which is generated as NULL because the joined table have no matching record.
Here is a query that returns only the rows where no correspondance has been found in both columns user_one and user_two of table2:
SELECT T1.*
FROM table1 T1
LEFT OUTER JOIN table2 T2A ON T2A.user_one = T1.id
LEFT OUTER JOIN table2 T2B ON T2B.user_two = T1.id
WHERE T2A.user_one IS NULL
AND T2B.user_two IS NULL
There is one jointure for each column (user_one and user_two) and the query only returns rows that have no matching jointure.
Hope this will help you.
SELECT table1.id
FROM table1
LEFT JOIN table2 ON table1.id = table2.user_one
WHERE table2.user_one is NULL
Try following query:-
SELECT table1.id
FROM table1
where table1.id
NOT IN (SELECT user_one
FROM Table2
UNION
SELECT user_two
FROM Table2)
Hope this helps you.
Try:
SELECT A.id FROM
(
SELECT table1.id FROM table1
LEFT JOIN table2 ON table1.id = table2.user_one
WHERE table2.user_one IS NULL
) A
JOIN (
SELECT table1.id FROM table1
LEFT JOIN table2 ON table1.id = table2.user_two
WHERE table2.user_two IS NULL
) B
ON A.id = B.id
See Demo
Or you could use two LEFT JOINS with aliases like:
SELECT table1.id FROM table1
LEFT JOIN table2 A ON table1.id = A.user_one
LEFT JOIN table2 B ON table1.id = B.user_two
WHERE A.user_one IS NULL
AND B.user_two IS NULL
See 2nd Demo
I am trying to make a query where 3 tables are being used. The first, table1, is used to store id values for table2 and table3 as well as some other data. In some cases there are no values stored in either of table2 or table3, some cases involve one or the other, and some involve both.
The issue is that when there are not values in either of table2 or table3, SQL attempts to look up NULL values as follows:
SELECT table1.id, table2value, table3value
FROM table1, table2, table3
WHERE table1value1 = table2.id AND table1value2 = table3.id;
So in this query if table1value1 or table1value2 are NULL, the query will not work as it is obviously not a valid link. So I am wondering how I would go about finding only the values that exist.
Use INNER JOIN instead. It joins the tables together with the condition of existing data in all tables. Else that row won't be returned.
SELECT table1.id, table2.value, table3.value
FROM table1
INNER JOIN table2
ON table1.value1 = table2.id
INNER JOIN table3
ON table1.value2 = table3.id;
But if you require for only one of these 2 rows to have existing data, you can do like this:
SELECT table1.id, table2.value, table3.value
FROM table1
LEFT JOIN table2
ON table1.value1 = table2.id
LEFT JOIN table3
ON table1.value2 = table3.id;
WHERE table2.id IS NOT NULL OR table3.id IS NOT NULL
Below query will return only matching rows with value exists in all 3 tables.
SELECT table1.id, table2value, table3value
FROM table1 inner join table2 on table1value1 = table2.id
inner join table3 on table1value2 = table3.id;
I think you need to use INNER JOIN, And by definition, the INNER JOIN keyword return rows when there is at least one match in both tables.
SELECT table1.id, table2.value, table3.value
FROM table1
INNER JOIN table2
ON table1.value1 = table2.id
INNER JOIN table3
ON table1.value2 = table3.id;
try This:
SELECT table1.id,
table2value,
table3value
FROM table1
JOIN table2
ON table1value1 = table2.id
JOIN table3
ON table1value2 = table3.id;
What about INNER JOIN
SELECT table1.id, table2value, table3value
FROM table1 INNER JOIN table2 ON table1.value1 = table2.id,
INNER JOIN table3 ON table1.value2 = table3.id;
You should use INNER JOIN.
SELECT table1.id, table2value, table3value
FROM table1
INNER JOIN table2 ON table1value1 = table2.id
INNER JOIN table3 ON table1value2 = table3.id;
Table1: ID,Name,some more columns
Table2: ID
Table3: Name
I want get output from table1, whose IDs are present in Table2.IDs & whose Name are present in Table3.Name.
In other words, select data which is present in ALL the 3 tables.
For ex:
Table1:
1 John
2 Will
3 Michael
Table2:
1
Table3:
Will
The output should be
1 John
2 Will
You need to use JOINs.
Your description and your sample output do not match, so I'll give you one example for each.
Based on your description, it should be 2 INNER JOINs:
select table1.id, table1.name
from table1
inner join table2 on table2.id = table1.id
inner join table3 on table3.name = table1.name
Based on your output, it should be 2 OUTER JOINS with a WHERE clause specifying that at least one of the 2 joins was satisfied:
select table1.id, table1.name
from table1
left outer join table2 on table2.id = table1.id
left outer join table3 on table3.name = table1.name
where table2.id is not null or table3.name is not null
Based on your expected results, it looks like you want rows from Table1 that match either Table2 OR Table3, so you'll want to use LEFT JOINs.
select t1.ID, t1.Name
from Table1 t1
left join Table2 t2
on t1.ID = t2.ID
left join table3 t3
on t1.Name = t3.Name
where t2.ID is not null
or t3.Name is not null