将条件放在ANSI语法SQL查询中的位置

时间:2010-06-09 19:26:24

标签: sql oracle ansi-sql

这两个查询有什么区别?我一直拒绝跳过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

6 个答案:

答案 0 :(得分:5)

是1)返回联接的产品,然后过滤掉那些重量> gt = 500的连接记录?并且2)过滤掉加入之前的那些?” / p>

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

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

答案 1 :(得分:3)

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

执行outer joins时,这不再是偏好问题 - 您放置BAR.WEIGHT < 500会对输出产生直接影响。

答案 2 :(得分:3)

如果你有OUTER JOINS,它会有所不同,那么你会得到不同的查询结果。

有关原因的解释,请参阅http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN

答案 3 :(得分:0)

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

但是,我很好奇 - 什么语法歧义引起了你的担忧?我更喜欢ANSI语法,因为对我而言,发生的事情要清楚得多。

分享并享受。

答案 4 :(得分:0)

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子句进行排序,以便将谓词逻辑分组。

答案 5 :(得分:0)

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

ON子句的条件仅适用于已连接的操作。

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

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

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

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