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 JOIN到INNER JOIN,只有从返回的行a用火柴从b上所有的条件。您可能想要一种行为或另一种行为,因此这些行为都不是“更糟”或“错误”,重要的是了解不同的功能,以便您知道编写查询以获得所需的结果。
| 归档时间: |
|
| 查看次数: |
25631 次 |
| 最近记录: |