这两个查询有什么区别?我一直拒绝跳过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
答案 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
案件是一个严重的问题。
在正确的地方添加条件具有以下附加优势,
inner join
更改为outer join
。不用担心条件。