WHERE 后跟 ON 子句
Posted
技术标签:
【中文标题】WHERE 后跟 ON 子句【英文标题】:WHERE followed by ON clause 【发布时间】:2021-05-30 14:34:54 【问题描述】:以下查询之间的语义差异是什么?对我来说,在我快速执行它们之前,它们看起来都很相似。这是 presto 特有的东西还是我在 SQL 标准中遗漏了什么?
形式一:ON子句中指定的所有条件。
SELECT
t1.colA,
t1.colB,
t1.colC,
t2.colD
FROM t1
LEFT OUTER JOIN t2
ON t1.colA = t2.colA
AND t1.colB = t2.colB
AND t1.colE = 1
AND t2.colF = 2;
形式2:改为WHERE子句中指定的一些条件。
SELECT
t1.colA,
t1.colB,
t1.colC,
t2.colD
FROM t1
LEFT OUTER JOIN t2
ON t1.colA = t2.colA
AND t1.colB = t2.colB
WHERE
t1.colE = 1
AND t2.colF = 2;
表格 1 产生一些行,但表格 2 没有,但它们不应该是等价的吗?
【问题讨论】:
【参考方案1】:有两个重要的区别。
首先是条件t1.colE = 1
。 LEFT JOIN
将所有行保留在第一个表中,而不管 ON
子句的计算结果如何。因此,t1.colE
不会更改结果集中的行数。但是,它确实具有奇怪的效果,即当此条件不成立时,来自t2
的任何列都是NULL
。
第二个条件t2.colF = 2
有不同的效果。这会将LEFT JOIN
转换为INNER JOIN
,因为NULL
值与WHERE
子句不匹配。
【讨论】:
【参考方案2】:当您有一个引用right_table
的LEFT [OUTER] JOIN
和WHERE
子句时,它等效于[INNER] JOIN
。也就是下面两个是等价的:
-- [inner] join
select ...
from left_table
join right_table
on left_table.cola = right_table.cola
and right_table.colb = 2
-- left [outer] join + where
select ...
from left_table
left join right_table
on left_table.cola = right_table.cola
where right_table.colb = 2
您的第二个示例查询在where
子句中有left join
和此条件t2.colF = 2
,使其与第一个查询不同。
第一个包括来自t1
的所有行,第二个只包括t1.colE = 1
和t2.colF = 2
的行
【讨论】:
【参考方案3】:思考WHERE
子句和ON
子句区别的方式是:
WHERE
子句确定在查询中应考虑FROM
子句生成的哪些行,因此它的作用是在行被GROUP BY
、WINDOW
或@ 处理之前对其进行过滤987654327@ 子句。
ON
子句确定是否应考虑将JOIN
左侧和右侧的一对行用于连接操作。
对于 INNER JOIN
,如果 ON
子句的计算结果为 false,则行不会相互连接,也不会发出任何结果。
对于LEFT JOIN
,如果对于左侧的给定行,ON
子句对于右侧的所有行的评估结果为 false,行包含左侧的值和 NULL 的列右侧发射。相同的逻辑适用于 RIGHT JOIN
,但两边颠倒了。
FULL JOIN
是 LEFT
和 RIGHT
的组合。
在您的示例中,第二个查询,由 LEFT JOIN
生成的任何行,由于 ON
子句评估为 false
而在右侧的列中包含 NULL,将被 t2.colF = 2
表达式过滤掉WHERE
子句。
【讨论】:
以上是关于WHERE 后跟 ON 子句的主要内容,如果未能解决你的问题,请参考以下文章