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
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
Suppose we have the need for a query performing two FULL JOINs (in PostgreSQL terminology) over table1-3, where table2 and table3 both have foreign keys pointing into table1. This shall work in MySQL, where FULL JOIN is not available. Thus a workaround has to be found.
Starting with LEFT JOINs, the following code works as described in (1):
SELECT table1.ID, table1.x, table2.y, table3.z
FROM (table1
LEFT JOIN table2
ON table1.ID = table2.FOREIGN_ID)
LEFT JOIN table3
ON table1.ID = table3.FOREIGN_ID
Following (2), I'm able to emulate a full outer join using the UNION statement for a single join:
SELECT table1.ID, table1.x, table2.y
FROM table1
LEFT JOIN table2
ON table1.ID = table2.FOREIGN_ID
UNION
SELECT table1.ID, table1.x, table2.y
FROM table1
RIGHT JOIN table2
ON table1.ID = table2.FOREIGN_ID
yielding
and
SELECT table1.ID, table1.x, table3.z
FROM table1
LEFT JOIN table3
ON table1.ID = table3.FOREIGN_ID
UNION
SELECT table1.ID, table1.x, table3.z
FROM table1
RIGHT JOIN table3
ON table1.ID = table3.FOREIGN_ID
ORDER BY ID
yielding
I need advice about how to get to this output from here:
That is, the result rows, which reference an entry from table1 via foreign key should be joined soundly, while the stray entries from table2 and table3 (those with foreign key NULL) should be listed in extra rows (y2 and z4 in the example).
Turned out that this would be a trivial two-step FULL JOIN with in PostgreSQL:
SELECT table1.id, table1.x, table2.y, table3.z
FROM table1
FULL JOIN table2
ON table2.Foreign_Id = table1.id
FULL JOIN table3
ON table3.Foreign_Id = table1.id
ORDER BY table1.id, table2.id, table3.id;
Shoutouts to the guys from freenode #sql pointing out this equivalent MySQL query, which avoids using FULL JOIN:
SELECT id1, x, y, z FROM (
SELECT table1.id as id1, table1.x, table2.id as id2, table2.y, table3.id as id3, table3.z
FROM table1
LEFT JOIN table2
ON table2.Foreign_Id = table1.id
LEFT JOIN table3
ON table3.Foreign_Id = table1.id
UNION ALL
SELECT NULL, NULL, table2.id, table2.y, NULL, NULL
FROM table2 WHERE NOT EXISTS (SELECT 1 FROM table1 WHERE table1.id = table2.Foreign_Id)
UNION ALL
SELECT NULL, NULL, NULL, NULL, table3.id, table3.z
FROM table3 WHERE NOT EXISTS (SELECT 1 FROM table1 WHERE table1.id = table3.Foreign_Id)
ORDER BY id1, id2, id3 ) AS T
I have two tables bound through an ID field:
table1: id, name, type
table2: id, id_table1, date, status
I have to collect all the records of the table1 that have a certain value of type field and that are not been referenced in table2 plus all the records of table1 referenced in table2 that have a certain status field value.
For the first part if I remember correctly I can use the LEFT JOIN command:
LEFT JOIN table1.name
LEFT JOIN table2
ON table2.id_table1 = table1.id
WHERE (table1.value = 'value1') AND (table2.id_table1 IS NULL);
but for the second part I'm getting lost...
I'm using MySQL 5.6 and I would like to define a View to handle this.
SELECT t1.*, t2.*
FROM table1 t1
LEFT JOIN table2 t2
ON table2.id_table1 = table1.id
WHERE (t1.type= 'value1' AND t2.id IS NULL)
OR (t2.status = 'certain status' )
I would think you could just change the WHERE to:
WHERE (table1.value = 'value1')
AND (table2.id_table1 IS NULL
OR
([the other table2 status criteria)
)
;
You can try this...
SELECT T1.*,T2.*
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.Id=T2.Id_Table1
WHERE T1.Value = 'value1' AND T2.id_table1 IS NULL
UNION
SELECT T1.*,T2.*
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.Id=T2.Id_Table1
WHERE T2.Status= 'Status Criteria'
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
Below is the my question any one have idea how to resolve this issue:
Example Query:
SELECT id, table2.id as global_id, table3.id as global_id
FROM table1
LEFT JOIN table2
ON ( table1.id = table2.tab1_id )
LEFT JOIN table3
ON ( table1.id = table3.tab1_id )
WHERE etc etc
Basically i don't want to write two times "global_id" column in the select statement and also in the some rows have id = NULL
Can you please write working query here. How can i get id value of all rows in the global_id column ?
Thanks
Use COALESCE:
SELECT table1.id, COALESCE(table2.id, table3.id) as global_id
FROM table1
LEFT JOIN table2
ON ( table1.id = table2.tab1_id )
LEFT JOIN table3
ON ( table1.id = table3.tab1_id )
WHERE etc etc
Guess you need this:
SELECT id, table2.id as global_id
FROM table1
LEFT JOIN table2
ON ( table1.id = table2.tab1_id )
WHERE etc etc
UNION ALL
SELECT id, table3.id as global_id
FROM table1
LEFT JOIN table3
ON ( table1.id = table3.tab1_id )
WHERE etc etc