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

Posted

技术标签:

【中文标题】(My)SQL 如何评估链式 LEFT/INNER JOIN?【英文标题】:How does (My)SQL evaluate chained LEFT/INNER JOINs? 【发布时间】:2013-12-15 20:30:20 【问题描述】:

我们有 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

现在我们测试了以下 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 = '%'

这个案子很清楚。结果:

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 = '%'

这个也清楚:

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 = '%'

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

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

我不明白 mysql 如何评估这个表达式。为什么它确实忽略了 LEFT JOIN 并且似乎更喜欢 INNER JOIN。

如果读到这个查询,就像:

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

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

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

【问题讨论】:

【参考方案1】:

INNER JOIN 应用于您已有的结果(即T1 LEFT JOIN T3),而不仅仅是T3

你读起来像:

(T1 LEFT JOIN (T3 INNER JOIN T2))

但它就像:

((T1 LEFT JOIN T3) INNER JOIN T2)

【讨论】:

【参考方案2】:

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

t1 left join (t2 inner join t3)

这与

有很大不同
(t1 left join t2) inner join t2

【讨论】:

以上是关于(My)SQL 如何评估链式 LEFT/INNER JOIN?的主要内容,如果未能解决你的问题,请参考以下文章

链式静态函数调用之间的参数评估顺序

Python 中的链式比较实际上是如何工作的?

评估链式过滤器时忽略过滤器分号的 FFmpeg 结尾

解析sql语句中left_joininner_join中的on与where的区别

SQL - 如何取出链式数据?

如何解决sql server 2012 评估期已过