鉴于这两个问题:
Select t1.id, t2.companyName
from table1 t1
INNER JOIN table2 t2 on t2.id = t1.fkId
WHERE t2.aField <> 'C'
或者:
Select t1.id, t2.companyName
from table1 t1
INNER JOIN table2 t2 on t2.id = t1.fkId and t2.aField <> 'C'
这两者之间是否存在明显差异?在我看来,条款“t2.aField&lt;&gt;'C'”将在t2中符合连接条件的每一行上运行,无论如何。我不对吗?
更新:我在SQL Server中执行了“包含实际执行计划”。这两个查询完全相同。
答案 0 :(得分:4)
我更喜欢使用Join标准来解释表格如何连接在一起。 所以我将附加条款放在where部分。
我希望(尽管我没有统计数据),无论您使用何种语法,SQL Server都能够聪明地找到最佳查询计划。
但是,如果您的索引也有id,并且其中包含aField,我建议将它们放在内连接条件中。
在这两个(或3个)场景中查看查询计划会很有趣,看看会发生什么。好问题。
答案 1 :(得分:3)
有区别。您应该为两个选项执行EXPLAIN PLAN并详细查看。
至于更简单的解释: WHERE子句只有在连接两个表后才会执行,因此它对从连接返回的每一行执行,而不是从table2中每个都执行。
性能方面最好尽早消除不需要的结果,因此连接的行数应该更少,以及后续处理的子句或其他操作。
在第二个例子中,要连接在一起的行有两列必须相同,所以它通常会得到与第一列不同的结果。
答案 2 :(得分:2)
取决于。
SELECT
t1.foo,
t2.bar
FROM
table1 t1
LEFT JOIN table2 t2 ON t1.SomeId = t2.SomeId
WHERE
t2.SomeValue IS NULL
与
不同SELECT
t1.foo,
t2.bar
FROM
table1 t1
LEFT JOIN table2 t2 ON t1.SomeId = t2.SomeId AND t2.SomeValue IS NULL
它是不同的,因为前者跨越了t2中所有在t2.SomeValue 中具有NULL的记录和来自t1的未在t2中引用的那些记录。后者仅跨越t2.SomeValue中具有NULL的t2记录。
只需对连接条件使用ON子句,对过滤器使用WHERE子句。
答案 3 :(得分:1)
除非将连接条件移动到where子句更改查询的含义(如上面的左连接示例中所示),否则放置它们的位置无关紧要。 SQL会重新安排它们,只要它们可以证明是等价的,你就会得到相同的查询。
话虽如此,我认为这更符合逻辑/可读性。我通常在连接中放置与两个表相关的任何内容,以及在where中过滤的任何内容。
答案 4 :(得分:0)
我更喜欢第一次查询。 SQL服务器将根据您拥有的索引为您的查询使用最佳连接类型,之后将应用WHERE子句。但是你可以同时运行两个查询,查看执行计划,比较并选择最快的(也可以优化添加索引)。
答案 5 :(得分:0)
除非您正在处理单用户应用程序或类似的小型应用程序,否则会产生微不足道的负载,唯一的考虑因素是服务器将如何处理您的查询。
提及查询计划的答案提供了很好的建议。
此外,设置io统计信息以了解您的查询将生成多少读取(我特别喜欢Azder的帖子)。
将每个数据库服务器视为从磁盘到客户端的数据泵。如果它只执行完成工作所需的IO,那么该泵会更快。如果数据在缓存中,它将更快。但是你不希望从磁盘读取超过你需要的东西 - 这将导致你的缓存中有用的数据被挤出,这是没有充分理由的。