07-27-2023, 12:26 PM
MySQL does not have FULL-OUTER-JOIN syntax. You have to emulate it by doing both LEFT JOIN and RIGHT JOIN as follows:
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
But MySQL also does not have a RIGHT JOIN syntax. According to MySQL's [outer join simplification][1], the right join is converted to the equivalent left join by switching the t1 and t2 in the `FROM` and `ON` clause in the query. Thus, the MySQL query optimizer translates the original query into the following -
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t2
LEFT JOIN t1 ON t2.id = t1.id
Now, there is no harm in writing the original query as is, but say if you have predicates like the WHERE clause, which is a [**before-join**][2] predicate or an AND predicate on the `ON` clause, which is a [**during-join**][3] predicate, then you might want to take a look at the devil; which is in details.
The MySQL query optimizer routinely checks the predicates if they are *null-rejected*.
[![Null-Rejected Definition and Examples][4]][4]
Now, if you have done the RIGHT JOIN, but with WHERE predicate on the column from t1, then you might be at a risk of running into a *null-rejected* scenario.
For example, the query
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'
gets translated to the following by the query optimizer:
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'
UNION
SELECT * FROM t2
LEFT JOIN t1 ON t2.id = t1.id
WHERE t1.col1 = 'someValue'
So the order of tables has changed, but the predicate is still applied to t1, but t1 is now in the 'ON' clause. If t1.col1 is defined as `NOT NULL`
column, then this query will be *null-rejected*.
Any outer-join (left, right, full) that is *null-rejected* is converted to an inner-join by MySQL.
Thus the results you might be expecting might be completely different from what the MySQL is returning. You might think its a bug with MySQL's RIGHT JOIN, but that’s not right. Its just how the MySQL query optimizer works. So the developer in charge has to pay attention to these nuances when he/she is constructing the query.
[1]:
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
But MySQL also does not have a RIGHT JOIN syntax. According to MySQL's [outer join simplification][1], the right join is converted to the equivalent left join by switching the t1 and t2 in the `FROM` and `ON` clause in the query. Thus, the MySQL query optimizer translates the original query into the following -
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t2
LEFT JOIN t1 ON t2.id = t1.id
Now, there is no harm in writing the original query as is, but say if you have predicates like the WHERE clause, which is a [**before-join**][2] predicate or an AND predicate on the `ON` clause, which is a [**during-join**][3] predicate, then you might want to take a look at the devil; which is in details.
The MySQL query optimizer routinely checks the predicates if they are *null-rejected*.
[![Null-Rejected Definition and Examples][4]][4]
Now, if you have done the RIGHT JOIN, but with WHERE predicate on the column from t1, then you might be at a risk of running into a *null-rejected* scenario.
For example, the query
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'
gets translated to the following by the query optimizer:
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'
UNION
SELECT * FROM t2
LEFT JOIN t1 ON t2.id = t1.id
WHERE t1.col1 = 'someValue'
So the order of tables has changed, but the predicate is still applied to t1, but t1 is now in the 'ON' clause. If t1.col1 is defined as `NOT NULL`
column, then this query will be *null-rejected*.
Any outer-join (left, right, full) that is *null-rejected* is converted to an inner-join by MySQL.
Thus the results you might be expecting might be completely different from what the MySQL is returning. You might think its a bug with MySQL's RIGHT JOIN, but that’s not right. Its just how the MySQL query optimizer works. So the developer in charge has to pay attention to these nuances when he/she is constructing the query.
[1]:
[To see links please register here]
[2]:[To see links please register here]
[3]:[To see links please register here]
[4]: