Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does (My)SQL evaluate chained LEFT/INNER JOINs?

We have 3 Tables given:

T1:               T2:              T3:

id | t3_id        id | name        id | t2_id
----------        ---------        ----------
1  | 2            1  | abc         1  | 1
2  | NULL         2  | 123         2  | 1
3  | 1            3  | ab1         3  | 3
4  | 4            4  | 32b         4  | 2

Now we had the following JOINs tested:

1.:

SELECT
  *
FROM T1
INNER JOIN T3 ON T1.t3_id = T3.id
INNER JOIN T2 ON T3.t2_id = T2.id
WHERE T2.name = '%'

This case is clear. Results:

T1.id | T1.t3_id | T3.id | T3.t2_id | T2.id | T2.name
-----------------------------------------------------
1     | 2        | 2     | 1        | 1     | abc
3     | 1        | 1     | 1        | 1     | abc
4     | 4        | 4     | 2        | 2     | 123

2.:

SELECT
  *
FROM T1
LEFT JOIN T3 ON T1.t3_id = T3.id
LEFT JOIN T2 ON T3.t2_id = T2.id
WHERE T2.name = '%'

This one is also clear:

T1.id | T1.t3_id | T3.id | T3.t2_id | T2.id | T2.name
-----------------------------------------------------
1     | 2        | 2     | 1        | 1     | abc
2     | NULL     | NULL  | NULL     | NULL  | NULL
3     | 1        | 1     | 1        | 1     | abc
4     | 4        | 4     | 2        | 2     | 123

3.:

SELECT
  *
FROM T1
LEFT JOIN T3 ON T1.t3_id = T3.id
INNER JOIN T2 ON T3.t2_id = T2.id
WHERE T2.name = '%'

This one is a bit strange. Result (same as the first one):

T1.id | T1.t3_id | T3.id | T3.t2_id | T2.id | T2.name
-----------------------------------------------------
1     | 2        | 2     | 1        | 1     | abc
3     | 1        | 1     | 1        | 1     | abc
4     | 4        | 4     | 2        | 2     | 123

I don't understand how MySQL evaluates this expression. Why it does ignore the LEFT JOIN and seems to prefer the INNER JOIN.

If I read this query it's like:

  1. Take data from T1
  2. Take data from T2 via LEFT JOIN (means: only if possible, else take NULL data)
  3. Take data from T3 via INNER JOIN (means: remove all T2 data that cannot be joined via this INNER JOIN)

But it seem's like I have to read the query backwards?!

Could someone please explain this scenario to me?

like image 446
Benjamin M Avatar asked Nov 29 '13 15:11

Benjamin M


People also ask

Does the order of left joins matter for performance?

For INNER joins, no, the order doesn't matter. The queries will return same results, as long as you change your selects from SELECT * to SELECT a.

Can left and inner join returns the same results?

Both queries return exactly the same result. This is not by accident but the result of the fact that this is the same query written in two different ways. Both ways are correct, and you can use any of them.

What is left inner join in MySQL?

The LEFT JOIN keyword returns all records from the left table (table1), and the matching records from the right table (table2). The result is 0 records from the right side, if there is no match.

How does LEFT join result in more rows?

There are two line items for ID 1003 in the second table, so the result of the join will be 2 line items. So, if your secondary tables have more than one row for the key you're joining with, then the result of the join will be multiple rows, resulting in more rows than the left table.


1 Answers

INNER JOIN is applied to the result you already have (ie T1 LEFT JOIN T3), not only to T3.

You read it like :

(T1 LEFT JOIN (T3 INNER JOIN T2))

But it's like :

((T1 LEFT JOIN T3) INNER JOIN T2)
like image 156
zessx Avatar answered Oct 13 '22 00:10

zessx