(My)SQL如何评估链接的LEFT / INNER JOIN?

Ben*_*n M 4 mysql sql join inner-join left-join

我们有3个表:

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
Run Code Online (Sandbox Code Playgroud)

现在我们已经测试了以下JOIN:

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 = '%'
Run Code Online (Sandbox Code Playgroud)

这种情况很明显。结果:

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
Run Code Online (Sandbox Code Playgroud)

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 = '%'
Run Code Online (Sandbox Code Playgroud)

这一点也很清楚:

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
Run Code Online (Sandbox Code Playgroud)

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 = '%'
Run Code Online (Sandbox Code Playgroud)

这个有点奇怪。结果(与第一个相同):

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
Run Code Online (Sandbox Code Playgroud)

我不明白MySQL如何评估这个表达式。为什么它会忽略LEFT JOIN而似乎更喜欢INNER JOIN。

如果阅读此查询,它就像:

  1. 从T1获取数据
  2. 通过LEFT JOIN从T2获取数据(意味着:仅在可能的情况下,否则获取NULL数据)
  3. 通过INNER JOIN从T3获取数据(意味着:删除所有无法通过此INNER JOIN连接的T2数据)

但是好像我必须向后读取查询?!

有人可以向我解释这种情况吗?

zes*_*ssx 5

INNER JOIN不仅应用于,还应用于您已有的结果(即T1 LEFT JOIN T3T3

你读它像:

(T1 LEFT JOIN (T3 INNER JOIN T2))
Run Code Online (Sandbox Code Playgroud)

但这就像:

((T1 LEFT JOIN T3) INNER JOIN T2)
Run Code Online (Sandbox Code Playgroud)


Jas*_*Heo 4

左连接类似于“OR”,而内连接类似于“AND”。所以有这样的优先级

t1 left join (t2 inner join t3)
Run Code Online (Sandbox Code Playgroud)

这与以下显着不同

(t1 left join t2) inner join t2
Run Code Online (Sandbox Code Playgroud)