将与表相关的条件放在 JOIN 中更好?

use*_*567 8 sql-server sql-server-2012

我已经看到很多人将与表相关的条件放在 JOIN 子句上。看这个例子,

SELECT i.Name
  FROM sys.TABLES AS tbl
  INNER JOIN sys.indexes AS i
    ON (i.index_id > 0 AND i.is_hypothetical = 0) 
    AND (i.object_id = tbl.object_id)
  WHERE (i.is_unique = 1 AND i.is_disabled = 0) 
    AND (tbl.Name = 'Warehouse')


SELECT i.Name
  FROM sys.TABLES AS tbl
  INNER JOIN sys.indexes AS i
    ON (i.object_id = tbl.object_id)
  WHERE (i.index_id > 0 AND i.is_hypothetical = 0) 
  AND (i.is_unique = 1 AND i.is_disabled = 0) 
  AND (tbl.Name = 'Warehouse')
Run Code Online (Sandbox Code Playgroud)

查询相同,但不同之处在于,第一个(i.index_id > 0 AND i.is_hypothetical = 0)在 JOIN 子句中使用,第二个在 WHERE 子句中使用相同。这对查询或性能有影响吗?

Aar*_*and 10

正如 JNK 所说,对于INNER JOIN,这些将是相同的。您可以通过比较实际(不要理会估计的)执行计划来证明这一点。在这种情况下,它们完全相同(点击放大):

在此处输入图片说明

就个人而言,我喜欢将连接条件和过滤条件分开。连接条件放在ON子句中,过滤条件放在WHERE子句中。这是首先使用显式INNER JOIN语法的主要好处之一,这有助于降低由于旧式连接中固有的连接条件不足(甚至没有)而返回过多行的风险(其中过滤器和连接条件被放在一起) -有关更多详细信息,请参阅此博客文章

JNK 也是对的,尽管您在谈论OUTER JOIN. 一个简单的例子:

CREATE TABLE dbo.a(id INT);

CREATE TABLE dbo.b(id INT, name SYSNAME);

INSERT dbo.a(id) VALUES(1),(2),(3);

INSERT dbo.b(id) VALUES(2,N'a'),(3,N'b');

SELECT a.id, b.name 
  FROM dbo.a 
  LEFT OUTER JOIN dbo.b
  ON a.id = b.id 
  AND b.name LIKE N'b%';

SELECT a.id, b.name
  FROM dbo.a 
  LEFT OUTER JOIN dbo.b
  ON a.id = b.id 
  WHERE b.name LIKE N'b%';
--^^^^^ only difference

DROP TABLE dbo.a, dbo.b;
Run Code Online (Sandbox Code Playgroud)

结果:

CREATE TABLE dbo.a(id INT);

CREATE TABLE dbo.b(id INT, name SYSNAME);

INSERT dbo.a(id) VALUES(1),(2),(3);

INSERT dbo.b(id) VALUES(2,N'a'),(3,N'b');

SELECT a.id, b.name 
  FROM dbo.a 
  LEFT OUTER JOIN dbo.b
  ON a.id = b.id 
  AND b.name LIKE N'b%';

SELECT a.id, b.name
  FROM dbo.a 
  LEFT OUTER JOIN dbo.b
  ON a.id = b.id 
  WHERE b.name LIKE N'b%';
--^^^^^ only difference

DROP TABLE dbo.a, dbo.b;
Run Code Online (Sandbox Code Playgroud)

正如你可以从结果看,第一个查询仍返回所有三行a(如你所期望的),但第二个查询转动OUTER JOININNER JOIN,只有从返回的行a用火柴从b所有的条件。您可能想要一种行为或另一种行为,因此这些行为都不是“更糟”或“错误”,重要的是了解不同的功能,以便您知道编写查询以获得所需的结果。