【问题标题】:Where to put conditionals in ANSI-syntax SQL queries在 ANSI 语法 SQL 查询中放置条件的位置
【发布时间】:2011-03-01 20:27:31
【问题描述】:

这两个查询有什么区别?我一直拒绝加入 ANSI 语法潮流,因为我无法解开各种语法歧义。

是 1) 返回连接的乘积,然后才过滤掉权重 >= 500 的连接记录吗?并且是 2) 在加入之前过滤掉那些吗?

2 语法不好?为什么我可以使用它?

1:

SELECT SOMETHING
FROM FOO
INNER JOIN BAR
ON FOO.NAME = BAR.NAME
WHERE BAR.WEIGHT < 500

2:

SELECT SOMETHING
FROM FOO
INNER JOIN BAR
ON FOO.NAME = BAR.NAME AND BAR.WEIGHT < 500

【问题讨论】:

    标签: sql oracle ansi-sql


    【解决方案1】:

    输出相同,因为它是inner join,查询计划应该相同。我更喜欢 #1 中的语法,因为它将 join 子句与 filter 子句分开,因此对我来说更具可读性。这使得在读取大型查询时更容易仔细检查您的 ON 子句,因为它减少了混合过滤子句时可能出现的噪音。

    在执行outer joins 时,这不再是偏好问题 - 您将BAR.WEIGHT &lt; 500 放在哪里会对输出产生直接影响。

    【讨论】:

      【解决方案2】:

      不同之处在于,当您有 OUTER JOINS 时,您将从查询中得到不同的结果。

      请参阅http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN 了解原因。

      【讨论】:

        【解决方案3】:

        是 1) 返回连接的乘积,然后才过滤掉权重 >= 500 的连接记录吗?以及 2) 过滤掉连接之前的那些记录?” p>

        true,除了 逻辑上,2) 将过滤器应用为连接的 part,而不是在加入之前。但是,对于 inner 连接,这种区别对查询的最终结果集没有影响。对于外连接,otoh,这种区别可以改变结果。

        注意:逻辑上使用这个词(说这是查询处理器逻辑上执行这些步骤的顺序)很重要,并且是字面意思。处理器使用的实际序列可能符合也可能不符合这个逻辑描述。仅保证查询的结果会出现,就好像处理器按此顺序执行这些步骤一样......

        【讨论】:

        • 我有点不同意。 SQL 是 4GL,并没有假装指定 如何 查询应该运行;它是对所需结果的规范。然而,我想,在向学生教授 SQL 时,以程序方式描述子句的工作方式可能会有所帮助。
        • @Jeffrey,也许我的注释措辞不好。这正是我打算传达的内容......“解释”没有描述查询处理器实际在做什么,只描述结果是什么......它只保证结果将look like处理器执行它们描述的序列...
        【解决方案4】:

        观察查询,您的陈述 1) 和 2) 似乎是正确的;但是,优化器可能有不同的意见。我建议你应该通过 EXPLAIN PLAN 运行这些查询,看看生成的计划是否真的不同。

        不过,我很好奇 - 什么语法歧义引起了您的担忧?我更喜欢 ANSI 语法,因为对我来说它更清楚发生了什么。

        分享和享受。

        【讨论】:

          【解决方案5】:

          2 语法不好?为什么我可以使用它?

          在 JOIN 子句或 WHERE 子句中放置谓词在语法上没有任何问题,无论哪种方式都适用于 Oracle。无论如何,Oracle 实际上并不关心 :)

          从逻辑上讲,我有时会使用 JOIN 和 WHERE 子句来使大型、复杂的查询更加自记录。例如:

          SELECT dept.name, SUM(emp.salary)
          FROM   dept
          JOIN   emp
                 ON dept.deptno = emp.deptno
                    AND emp.commission IS NULL
          WHERE  dept.region = :region
          GROUP BY dept.name;
          

          此查询具有三个谓词,其中一个是连接条件。我已将 emp.commission 谓词放在 JOIN 子句中,以向其他开发人员表明这是“不可协商的”——在此查询的上下文中,谓词应该始终存在。 dept.region 谓词位于 WHERE 子句中,表明它是用户提供的条件。

          这是一种风格选择,没有规则,我不会一直这样做。但是,当查询连接许多表并且有几十个谓词时,它会有所帮助。 JOIN 子句允许对谓词很好地“分组”,否则我们将对 WHERE 子句进行排序,以便谓词在逻辑上组合在一起。

          【讨论】:

            【解决方案6】:

            WHERE 子句的条件应用于最终结果集。

            ON 子句上的条件仅适用于联合操作。

            因此确定最终结果集和连接操作的条件,然后将它们添加到正确的位置。

            INNER JOIN 的情况下没有区别,因为每个内连接操作都负责最终的结果集(外连接操作不是这样)。因此,对于outer join 案例来说,这是一个严重的问题。

            在正确的位置添加条件具有以下附加优势,

            1. 可维护
              • 易于从inner join 更改为outer join。不用担心条件。
              • 很容易从查询中删除连接表。
              • 易于更改应用程序特定条件。 即所有场景的连接条件都是相同的。但应用程序特定条件(在 WHERE 条件内)可能因场景而异。
            2. 可读:更容易识别表之间的关系。

            【讨论】:

              猜你喜欢
              • 2022-01-04
              • 1970-01-01
              • 2020-02-20
              • 2014-07-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-11-22
              相关资源
              最近更新 更多