WHERE 后跟 ON 子句
WHERE followed by ON clause
以下查询之间的语义区别是什么?对我来说,两者看起来很相似,直到我立即执行它们。这是 presto 特有的东西还是我在 SQL 标准中遗漏了什么?
形式 1: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;
形式二:部分条件在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 不会,但它们不应该是等价的吗?
有两个重要区别。
首先是条件t1.colE = 1
。 LEFT JOIN
保留第一个 table 中的所有行,而不管 ON
子句的计算结果。因此,t1.colE
不会更改结果集中的行数。然而,当这个条件不成立时,t2
中的任何列都是 NULL
.
第二个条件t2.colF = 2
有不同的效果。这会将 LEFT JOIN
变成 INNER JOIN
,因为 NULL
值与 WHERE
子句不匹配。
当您有引用 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
的行
思考WHERE
子句和ON
子句区别的方法是:
-
WHERE
子句确定查询中应考虑由 FROM
子句生成的哪些行,因此它的作用是在行被 [=14= 处理之前对其进行过滤]、WINDOW
或 SELECT
子句。
-
ON
子句确定是否应考虑将 JOIN
左右两侧的一对行用于连接操作。
- 对于
INNER JOIN
,如果 ON
子句的计算结果为 false,则行不会相互连接并且不会发出任何结果。
- 对于
LEFT JOIN
,如果对于左侧的给定行,ON
子句对右侧所有行的计算结果为 false,则包含左侧值的行并发出右侧列的 NULL。同样的逻辑适用于 RIGHT JOIN
,但两侧相反。
FULL JOIN
是 LEFT
和 RIGHT
联接的组合。
在您的示例中,第二个查询,由于 ON
子句评估为 false
,由 LEFT JOIN
生成的任何行在右侧的列中包含 NULL 将是由 t2.colF = 2
表达式 WHERE
子句过滤掉。
以下查询之间的语义区别是什么?对我来说,两者看起来很相似,直到我立即执行它们。这是 presto 特有的东西还是我在 SQL 标准中遗漏了什么?
形式 1: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;
形式二:部分条件在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 不会,但它们不应该是等价的吗?
有两个重要区别。
首先是条件t1.colE = 1
。 LEFT JOIN
保留第一个 table 中的所有行,而不管 ON
子句的计算结果。因此,t1.colE
不会更改结果集中的行数。然而,当这个条件不成立时,t2
中的任何列都是 NULL
.
第二个条件t2.colF = 2
有不同的效果。这会将 LEFT JOIN
变成 INNER JOIN
,因为 NULL
值与 WHERE
子句不匹配。
当您有引用 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
思考WHERE
子句和ON
子句区别的方法是:
-
WHERE
子句确定查询中应考虑由FROM
子句生成的哪些行,因此它的作用是在行被 [=14= 处理之前对其进行过滤]、WINDOW
或SELECT
子句。 -
ON
子句确定是否应考虑将JOIN
左右两侧的一对行用于连接操作。- 对于
INNER JOIN
,如果ON
子句的计算结果为 false,则行不会相互连接并且不会发出任何结果。 - 对于
LEFT JOIN
,如果对于左侧的给定行,ON
子句对右侧所有行的计算结果为 false,则包含左侧值的行并发出右侧列的 NULL。同样的逻辑适用于RIGHT JOIN
,但两侧相反。 FULL JOIN
是LEFT
和RIGHT
联接的组合。
- 对于
在您的示例中,第二个查询,由于 ON
子句评估为 false
,由 LEFT JOIN
生成的任何行在右侧的列中包含 NULL 将是由 t2.colF = 2
表达式 WHERE
子句过滤掉。