【问题标题】:WHERE followed by ON clauseWHERE 后跟 ON 子句
【发布时间】: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 没有,但它们不应该是等价的吗?

【问题讨论】:

    标签: mysql sql presto trino


    【解决方案1】:

    有两个重要的区别。

    首先是条件t1.colE = 1LEFT JOIN 将所有行保留在第一个表中,而不管 ON 子句的计算结果如何。因此,t1.colE 不会更改结果集中的行数。但是,它确实具有奇怪的效果,即当此条件不成立时,来自t2 的任何列都是NULL

    第二个条件t2.colF = 2有不同的效果。这会将LEFT JOIN 转换为INNER JOIN,因为NULL 值与WHERE 子句不匹配。

    【讨论】:

      【解决方案2】:

      当您有一个引用right_tableLEFT [OUTER] JOINWHERE 子句时,它等效于[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 = 1t2.colF = 2 的行

      【讨论】:

        【解决方案3】:

        思考WHERE子句和ON子句区别的方式是:

        • WHERE 子句确定在查询中应考虑FROM 子句生成的哪些行,因此它的作用是在行被GROUP BYWINDOW 或@ 处理之前对其进行过滤987654327@ 子句。
        • ON 子句确定是否应考虑将JOIN 左侧和右侧的一对行用于连接操作。
          • 对于 INNER JOIN,如果 ON 子句的计算结果为 false,则行不会相互连接,也不会发出任何结果。
          • 对于LEFT JOIN,如果对于左侧的给定行,ON 子句对于右侧的所有行的评估结果为 false,行包含左侧的值和 NULL 的列右侧发射。相同的逻辑适用于 RIGHT JOIN,但两边颠倒了。
          • FULL JOINLEFTRIGHT 的组合。

        在您的示例中,第二个查询,由 LEFT JOIN 生成的任何行,由于 ON 子句评估为 false 而在右侧的列中包含 NULL,将被 t2.colF = 2 表达式过滤掉WHERE 子句。

        【讨论】:

          猜你喜欢
          • 2013-08-02
          • 1970-01-01
          • 1970-01-01
          • 2010-11-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-07
          • 2017-11-18
          相关资源
          最近更新 更多