I have two tables:
T1
1,a
2,b
T2
2,ggg
3,hhh
I want the join between them to give me all fields:
1,a,null,null
2,b,2,ggg
null,null,3,hhh
MySQL doesn't have FULL OUTER JOIN, but you can emulate it e.g.:
SELECT * FROM T1 LEFT OUTER JOIN T2 ON T1.id = T2.id
UNION ALL
SELECT * FROM T1 RIGHT OUTER JOIN T2 ON T1.id = T2.id
WHERE T1.id IS NULL;
In general:
FULL OUTER JOIN = LEFT OUTER JOIN ∪ (RIGHT OUTER JOIN ∖ INNER JOIN)
You need to cut one inner join (in here from right join, but IMHO doesn't matter which one you choose), because both returns same inner joins. In here you have:
T1::
T2::
LEFT OUTER JOIN::
RIGHT OUTER JOIN::
INNER JOIN::
FULL OUTER JOIN::
If the tables have a (combination of) columns that is unique, you can build a list of ids in a subquery. Then you can use two outer joins to simulate a full outer join:
select *
from (
select col1
from t1
union
select col1
from t2
) ids
left join
t1
on ids.col1 = t1.col1
left join
t2
on ids.col1 = t2.col1
Related
SELECT t1.*, IFNULL(t2.profile_id, t3.profile_id) AS `profile_id`
FROM table1 AS t1
LEFT JOIN table2 AS t2
ON t1.id = t2.some_coulmn
LEFT JOIN table3 AS t3
ON t1.id = t3.some_coulmn
LEFT JOIN table4 AS t4
ON profile_id = t4.some_column
I'm trying to use an alias (profile_id) inside my join condition. It fails. Is there a way to do this?
Column aliases defined in th SELECT clause cannot be used in the join conditions. This is because the FROM clause is evaluated before the SELECT clause.
If I followed you correctly, you probably want:
SELECT t1.*, IFNULL(t2.profile_id, t3.profile_id) AS `profile_id`
FROM table1 AS t1
LEFT JOIN table2 AS t2
ON t1.id = t2.some_coulm
LEFT JOIN table3 AS t3
ON t1.id = t3.some_coulm
LEFT JOIN table4 AS t4
ON IFNULL(t2.profile_id, t3.profile_id) = t4.some_column
Are there significant performance considerations between using UNION versus LEFT OUTER JOIN with OR in the WHERE clause?
What is the difference between these two queries?
Is it often better to use LEFT OUTER JOINs instead of a UNION?
My reason for asking is I actually need to do an INSERT, and can't use a UNION even if I wanted to.
SELECT t.foo
FROM t
INNER JOIN t1 t1.t_id=t.id
WHERE t1.id IN (1,2,3)
UNION
SELECT t.foo
FROM t
INNER JOIN t2 t2.t_id=t.id
INNER JOIN t2a ON t2a.t2_id=t2.id
WHERE t2a.id IN (1,2,3)
UNION
SELECT t.foo
FROM t
INNER JOIN t3 t3.t_id=t.id
INNER JOIN t3a ON t3a.t3_id=t3.id
WHERE t3a.id IN (1,2,3);
SELECT DISTINCT t.foo
FROM t
LEFT OUTER JOIN t1 t1.t_id=t.id
LEFT OUTER JOIN t2 t2.t_id=t.id
LEFT OUTER JOIN t2a ON t2a.t2_id=t2.id
LEFT OUTER JOIN t3 t3.t_id=t.id
LEFT OUTER JOIN t3a ON t3a.t3_id=t3.id
WHERE t1.id IN (1,2,3) OR t2a.id IN (1,2,3) OR t3a.id IN (1,2,3);
UPDATE t
LEFT OUTER JOIN t1 t1.t_id=t.id
LEFT OUTER JOIN t2 t2.t_id=t.id
LEFT OUTER JOIN t2a ON t2a.t2_id=t2.id
LEFT OUTER JOIN t3 t3.t_id=t.id
LEFT OUTER JOIN t3a ON t3a.t3_id=t3.id
SET t.foo="bar"
WHERE t1.id IN (1,2,3) OR t2a.id IN (1,2,3) OR t3a.id IN (1,2,3);
As with many performance questions, you should test the results on your data and your systems. The union and left joins are doing very different things -- and which is better probably depends on features of your data, available indexes, and other considerations.
However, you can use the union method in update. You just need a subquery:
update t join
(select t.id, t1.foo . . .
union . . .
select t.id, t2.foo
) tt
on t.id = tt.id
set t.foo = 'foo'
where . . .;
You might also find it more efficient to use the union approach but to break the update into multiple separate update statements.
You can use UNION in inserts.
INSERT INTO `table`
SELECT * FROM
(
SELECT '1'
UNION
SELECT '2'
) x
Same goes for updates:
UPDATE `table1` t1
JOIN (
SELECT '1' as col1
UNION
SELECT '2'
) x ON x.col1 = t1.colX
SET t1.whateverColumn = "someValue"
As for performance, it's mainly down to indexes. Both can be fast, both can be slow. If you're indexing them correctly, you shouldn't see big differences between the two.
Are there any circumstances that would cause different number of records returned from a query that includes inner joins and outer joins depending on the order of the joins?
As a simple example, could there be any difference in the resultset generated by this query:
SELECT *
FROM table1
JOIN table2 on table1.id = table2.id
LEFT OUTER join table3 ON table1.id = table3.id
....or by this query which differ only by the 2 join conditions being swapped
SELECT *
FROM table1
LEFT OUTER join table3 ON table1.id = table3.id
JOIN table2 on table1.id = table2.id
For INNER JOIN order doesn't matter. But for OUTER JOIN it does.
'Table1 JOIN Table2' is same as 'Table2 JOIN Table1'
But,
'Table1 LEFT JOIN Table2' is not same as 'Table2 LEFT JOIN Table1'
Outer Joins are neither commutative nor associative. You may checkout EXPLAIN PLAN to understand the performance difference.
Suppose I have following tables: T1,T2 and T3.
How could I rephrase the following query using only left joins.
Select *
From T1
Right join T2 On T1.FK2=T2.PK
Right join T3 On T1.FK3=T3.PK
Following attempt is not correct:
Select *
From T2
Left join T1 On T1.FK2=T2.PK
Left join T3 On T1.FK3=T3.PK
T3 is On the wrong Side of the join. Is the following possible:
Select *
From T2
Left join T3 On T1.FK3=T3.PK
Left join T1 On T1.FK2=T2.PK
I can't Find a way to put both tables 2 and 3 On the left Side of 1 and use the correspondent fields to join all tables? The last query uses fields of table 1 before this table is mentioned in the query.
Or something like this?
Select *
From T2
Left join (
T3 left join T1
On T1.FK3=T3.PK)
On T1.FK2=T2.PK
Apparently brackets can help to order your joins. I wonder if this is really documented, i've found Nothing at first glance in the mysql docs.
Following query is correct and does not have any subqueries:
Select T1.Id Ida, t2.id idb, T3.id idc FROM T3
LEFT JOIN
(T2
LEFT JOIN T1 ON (T1.ID = T2.ID))
ON (T1.ID= T3.ID);
You need to use a subquery to first join t1 with t2 and then join the result with t3:
SELECT T.ID1 ID1, T.ID2 ID2, T3.ID ID3 FROM T3
LEFT JOIN
(SELECT T1.ID ID1, T2.ID ID2 FROM T2
LEFT JOIN T1 ON (T1.ID = T2.ID)) T
ON (T.ID1 = T3.ID);
SQL Fiddle
The first way is just to reverse the order that the tables are mentioned:
Select *
from t3 left outer join
t2
on T1.FK3 = T3.PK left outer join
t1
on T1.FK2 = T2.PK
But this won't work, because the first condition is on t1 and not t2. And t2 hasn't yet been defined.
When working with chains of tables in left or right outer joins, only the first (or last) tables are important, because they "drive" the query. "Drive" in the sense that they provide all the values even when there are no matches. So, the following should do what you want:
Select *
from t3 left outer join
t1
on T1.FK3 = T3.PK left outer join
t2
on T1.FK2 = T2.PK;
Is there an easier way to left join parent data to multiple child left join data?
Table Structure:
Table1 {id, name, data1, data2, datax}
Table2 {id, table1_id, dataA, dataB, userid}
Table3 {id, table1_id, dataD, userid}
Table4 {id, table1_id, dataE, userid}
TableUsers {userid, username, name, email}
SQL Query:
select Table1.*, Table2.*,Table3.*,Table4.*
from Table1 t1
left outer join Table2 t2 on t2.table1_id = t1.id
left outer join Table3 t3 on t3.table1_id = t1.id
left outer join Table4 t4 on t4.table1_id = t1.id
From here I want to replace the userid field with the actual user name and each table will have different data for userid so a simple left join with TableUsers won't work since it will only take affect for the table it is set equal to.
I have thought about doing it with a sub query, but believe that would be extra slow:
select Table1.*,(select TableUser.name from TableUser where Table1.userid = TableUser.userid) as T1Name,
Table2.*,(select TableUser.name from TableUser where Table2.userid = TableUser.userid) as T2Name,
Table3.*, (select TableUser.name from TableUser where Table3.userid = TableUser.userid) as T3Name,
Table4.*,(select TableUser.name from TableUser where Table1.userid = TableUser.userid) as T4Name
from Table1 t1
left outer join Table2 t2 on t2.table1_id = t1.id
left outer join Table3 t3 on t3.table1_id = t1.id
left outer join Table4 t4 on t4.table1_id = t1.id
The point of this is to move from an SQL database to MongoDB. Perhaps I need to rethink this entire query...
Cheers,
Chip
The "normal" way to do this would be to add additional joins:
select Table1.*, t1name.name, Table2.*, t2name.name, Table3.*, t3name.name,
Table4.*, t4name.name
from Table1 t1
left outer join Table2 t2 on t2.table1_id = t1.id
left outer join Table3 t3 on t3.table1_id = t1.id
left outer join Table4 t4 on t4.table1_id = t1.id
left outer join TableUser t1name on t1.userid = t1name.userid
left outer join TableUser t2name on t2.userid = t2name.userid
left outer join TableUser t3name on t3.userid = t3name.userid
left outer join TableUser t4name on t4.userid = t4name.userid;
If you have an indexon TableUser(userid) or TableUser(userid, name), then the performance of the two methods should be about the same.