简体   繁体   English

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

[英]Where to put conditionals in ANSI-syntax SQL queries

What's the difference between these two queries? 这两个查询之间有什么区别? I've been resistant to jumping on the ANSI-syntax bandwagon because I have not been able to unravel various syntactical ambiguities. 我一直拒绝跳过ANSI语法的潮流,因为我无法解开各种语法歧义。

Is 1) returning the product of the join and only then filtering out those joined records which have weight >= 500? 是1)返回连接的产品,然后过滤掉那些重量> = 500的连接记录? And is 2) filtering out those prior to the join? 并且2)过滤掉加入之前的那些?

Is 2 bad syntax? 2语法不好吗? Why might I use that? 我为什么要用它?

1: 1:

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

2: 2:

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

" Is 1) returning the product of the join and only then filtering out those joined records which have weight >= 500? And is 2) filtering out those prior to the join ?" 是1)返回连接的产品,然后过滤掉那些重量> = 500的连接记录?并且2)过滤掉连接之前的那些 ?”

true, except that logically , 2) is applying the filter as part of the join, not prior to the the join. 是的,除了在逻辑上 ,2)将过滤器作为连接的一部分应用,而不是在连接之前。 For an inner join, however, this distinction will have no effect on the final resultset of the query. 但是,对于内部联接,此区别对查询的最终结果集没有影响。 For Outer joins, otoh, this distinction can alter the results. 对于外连接,otoh,这种区别可以改变结果。

NOTE : Using the word logically (saying that this is the sequence in which the query processor logically performs these steps) is important, and is meant literally. 注意 :使用逻辑上的单词(说这是查询处理器逻辑上执行这些步骤的顺序)很重要,并且字面意思。 The actual sequence used by the proccessor may or may not conform to this logical description. 进程者使用的实际序列可能符合也可能不符合该逻辑描述。 It is only guaranteeed that the results of the query will appear as though the processor performed these steps in this order... 只保证查询结果看起来好像处理器按此顺序执行这些步骤...

The output is the same since it is an inner join , and the query plan should be the same. 输出是相同的,因为它是inner join ,并且查询计划应该是相同的。 I prefer the syntax in #1 as it separates the joining clause from the filter clause, and is thus more readable to me. 我更喜欢#1中的语法,因为它将join子句与filter子句分开,因此对我来说更具可读性。 This makes it easier to double-check your ON clauses when reading over a large query, as it reduces the noise that would be there if filter clauses were mixed in. 这样可以更轻松地在读取大型查询时仔细检查ON子句,因为它可以减少混合过滤子句时的噪音。

When doing outer joins , this is no longer a matter of preference - where you put BAR.WEIGHT < 500 would have a direct effect on the output. 在进行outer joins ,这不再是首选问题 - 您将BAR.WEIGHT < 500放在输出上会产生直接影响。

Where it makes a difference is when you have OUTER JOINS, then you will get different results from the queries. 它产生影响的地方在于你有OUTER JOINS,那么你将得到不同的查询结果。

See http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN for explanation as to why. 有关原因的解释,请参见http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN

Eyeballing the queries it certainly seems that your statements 1) and 2) might be correct; 仔细观察这些问题肯定似乎你的陈述1)和2)可能是正确的; however, the optimizer may have a different opinion. 但是,优化器可能有不同的意见。 I suggest you should run these queries through EXPLAIN PLAN and see if the generated plans are actually different. 我建议你应该通过EXPLAIN PLAN运行这些查询,看看生成的计划是否真的不同。

I'm curious, though - what syntactical ambiguities are causing you concerns? 不过我很好奇 - 什么语法歧义引起了你的担忧? I much prefer the ANSI syntax because to me it's much clearer what's going on. 我更喜欢ANSI语法,因为对我来说更清楚的是发生了什么。

Share and enjoy. 分享和享受。

Is 2 bad syntax? 2语法不好吗? Why might I use that? 我为什么要用它?

There's nothing wrong syntactically with placing a predicate in the JOIN clause or in the WHERE clause, either way works in Oracle. 在JOIN子句或WHERE子句中放置谓词在语法上没有任何错误,无论哪种方式都适用于Oracle。 Oracle doesn't actually care anyway :) Oracle实际上并不关心:)

Logically, I will sometimes use the JOIN and WHERE clauses to make large, complicated queries more self-documenting. 从逻辑上讲,我有时会使用JOIN和WHERE子句来使大型复杂查询更加自我记录。 For example: 例如:

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;

This query has three predicates, one of which is a join criterion. 此查询有三个谓词,其中一个是连接标准。 I've put the emp.commission predicate in the JOIN clause to indicate to other developers that this is a "non-negotiable" - in the context of this query that predicate should always be there. 我将emp.commission谓词放在JOIN子句中,以向其他开发人员表明这是一个“不可协商的” - 在此查询的上下文中,谓词应始终存在。 The dept.region predicate is in the WHERE clause to indicate that it is the user-supplied criteria. dept.region谓词位于WHERE子句中,表示它是用户提供的条件。

This is a style choice, there is no rule, and I wouldn't do it this way all the time. 这是一种风格选择,没有规则,我不会一直这样做。 It helps, however, when a query joins many tables, and when there are dozens of predicates. 但是,当查询加入许多表时,以及存在数十个谓词时,它会有所帮助。 The JOIN clauses allow predicates to be "grouped" nicely, where otherwise we'd sort the WHERE clause so that predicates were grouped together logically. JOIN子句允许谓词很好地“分组”,否则我们会对WHERE子句进行排序,以便将谓词逻辑地组合在一起。

Conditions on the WHERE clause are applied to the final result-set. WHERE子句的条件应用于最终结果集。

Conditions on the ON clause are only applied to the joined operation. ON子句的条件仅适用于连接操作。

So identify the conditions for the final result-set and join operations, then add them in the right place. 因此,确定最终结果集和连接操作的条件,然后将它们添加到正确的位置。

In the case of INNER JOIN there is no difference, because each and every inner join operations are responsible for the final result-set (not true for outer join operation). INNER JOIN的情况下没有区别,因为每个内部INNER JOIN操作都负责最终的结果集(对于外部INNER JOIN操作不是这样)。 So it is a serious issue for outer join cases. 因此,对于outer join案例来说这是一个严重的问题。

Adding the conditions in the right place has following added advantages, 在正确的地方添加条件具有以下附加优势,

  1. Maintainable 可维护性
    • Easy to change from inner join to outer join . 易于从inner join更改为outer join No worries about conditions. 不用担心条件。
    • Easy to remove a join table from the query. 易于从查询中删除连接表。
    • Easy to change application specific conditions. 易于更改特定应用条件。 ie Join conditions are same for all the scenarios. 即连接条件对于所有场景都是相同的。 But application specific conditions (inside WHERE conditions) may vary for scenario to scenario. 但是应用程序特定条件(在WHERE条件内)可能因场景而异。
  2. Readable: Easier to identify the relationships between tables. 可读:更容易识别表之间的关系。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM