在JOIN或WHERE内条件

在JOIN子句和WHERE子句之间join条件有什么区别(性能,最佳实践等)?

例如…

-- Condition in JOIN SELECT * FROM dbo.Customers AS CUS INNER JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID AND CUS.FirstName = 'John' -- Condition in WHERE SELECT * FROM dbo.Customers AS CUS INNER JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID WHERE CUS.FirstName = 'John' 

你喜欢哪个(也许是为什么)?

关系代数允许谓词在WHERE子句和INNER JOIN互换,所以即使使用WHERE子句的INNER JOIN查询也可以使优化器重新排列的谓词,以便在JOIN过程中它们可能已被排除

我build议你以最可读的方式编写查询。

有时这包括使INNER JOIN相对“不完整”,并将WHERE中的一些条件放在一起,以简化过滤条件列表。

例如,而不是:

 SELECT * FROM Customers c INNER JOIN CustomerAccounts ca ON ca.CustomerID = c.CustomerID AND c.State = 'NY' INNER JOIN Accounts a ON ca.AccountID = a.AccountID AND a.Status = 1 

写:

 SELECT * FROM Customers c INNER JOIN CustomerAccounts ca ON ca.CustomerID = c.CustomerID INNER JOIN Accounts a ON ca.AccountID = a.AccountID WHERE c.State = 'NY' AND a.Status = 1 

但是,这当然取决于。

对于内部连接,我并没有真正注意到其中的差异(但是与所有的性能调优一样,你需要在你的条件下检查你的数据库)。

但是,如果您使用左连接或右连接,则放置条件会产生巨大的差异。 例如考虑这两个查询:

 SELECT * FROM dbo.Customers AS CUS LEFT JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID WHERE ORD.OrderDate >'20090515' SELECT * FROM dbo.Customers AS CUS LEFT JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID AND ORD.OrderDate >'20090515' 

第一个将只给你那些订单date比2009年5月15日晚的logging,从而将左连接转换为内连接。 第二个将给这些logging加上任何没有订单的客户。 结果集是非常不同的,取决于你把条件放在哪里。 (select*如果只是为了举例的目的,当然不应该在生产代码中使用)。例外是当你只想看到一个表中的logging,而不是另一个时。 然后,您使用where子句的条件而不是连接。

 SELECT * FROM dbo.Customers AS CUS LEFT JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID WHERE ORD.OrderID is null 

大多数RDBMS产品将同样优化两个查询。 在Peter Gulutzan和Trudy Pelzer的“SQL Performance Tuning”中,他们testing了多个品牌的RDBMS,没有发现任何性能差异。

我希望保持连接条件与查询限制条件分开。

如果您使用OUTER JOIN有时需要在join子句中添加条件。

JOIN发生后,将在哪里进行筛选。

在JOIN上过滤以防止在JOIN过程中添加行。

我更喜欢JOINjoin完整的表/视图,然后使用WHERE来介绍结果集的谓词。

它感觉语法更清洁。

我通常看到在连接上进行筛选时性能会提高。 特别是如果你可以join两个表的索引列。 大多数查询也可以减less逻辑读取,也就是说,在高容量环境下,性能指标比执行时间要好得多。

当有人展示他们的SQL基准testing,并且他们已经在开发服务器上午夜两次执行了5万次sproc的版本,并且比较平均时间时,我总是感到有些好笑。

把条件join连接看起来对我来说是“语义上错误的”,因为这不是JOIN的“for”。 但这是非常定性的。

额外的问题:如果你决定从一个内部连接切换到一个正确的连接,条件是在JOIN内可能会导致意想不到的结果。

当我有一个更大的桌子时,join更快。 这真的没什么区别,特别是如果你正在处理一个更小的表格。 当我第一次了解到连接时,我被告知连接中的条件就像where子句的条件一样,如果where子句具体关于哪个表做条件,我可以互换使用它们。