SQL中有两个选择或一个选择+一个连接?

时间:2013-11-07 12:05:25

标签: sql sql-server-2008 join inner-join

以下代码段应该执行相同的工作。

SELECT t1.* FROM table1 t1
INNER JOIN table2 t2
ON t1.ID = t2.IDService
WHERE t2.Code = @code

SELECT * FROM table1 t1
WHERE t1.ID IN (SELECT IDService FROM table2 WHERE Code = @code)

一般来说哪一个是最好的解决方案?而在计算上,最好有两个嵌套选择还是更好用内连接?

修改 考虑到table1的PK为ID,而table2的PK为该对(IDService,Code)。因此,修复代码(使用WHERE子句)并将ON子句应用于IDService,我可以假设每个选择的结果都是相同的。

2 个答案:

答案 0 :(得分:0)

作为一般规则, JOIN 几乎总是比 SUB-QUERY 表现更好,但有例外情况。

如果要使用子查询, EXIST 子句,对于大多数用例,通常比 IN 表现更好。

对于测试用例,您可以查看此site

你应该遵循以下规则......

  1. 如果您需要来自多个表的数据,那么您可以随时加入。

  2. 如果需要多个查询,并且每个子查询都提供查询中涉及的表的子集,则可以使用子查询。

  3. 如果查询需要NOT EXISTS条件,则必须使用子查询,因为NOT EXISTS仅在子查询中运行;同样的原则适用于EXISTS条件。

  4. 程序SQL查询优化器将一些子查询更改为连接,通常更有效地处理连接。

答案 1 :(得分:0)

你认为他们应该做同样的工作是不正确的。想象一下这组测试数据:

<强> T1

ID
----
1
2
3
4
5

<强> T2

ID
---
1
1
1
2
2
3

<强> DDL

CREATE TABLE dbo.T1 (ID INT NOT NULL);
INSERT dbo.T1 (ID) VALUES (1), (2), (3), (4), (5);

CREATE TABLE dbo.T2 (ID INT NOT NULL);
INSERT dbo.T2 (ID) VALUES (1), (1), (1), (2), (2), (3);

SELECT  *
FROM    dbo.T1
WHERE   T1.ID IN (SELECT T2.ID FROM dbo.T2);

SELECT  T1.*
FROM    dbo.T1
        INNER JOIN dbo.T2
            ON T1.ID = T2.ID;

<强>结果

ID
---
1
2
3

ID
---
1
1
1
2
2
3

如果您要搜索的列是唯一的,则结果仅相同。

CREATE TABLE dbo.T1 (ID INT NOT NULL);
INSERT dbo.T1 (ID) VALUES (1), (2), (3), (4), (5);

CREATE TABLE dbo.T2 (ID INT NOT NULL);
INSERT dbo.T2 (ID) VALUES (1), (2), (3);

SELECT  *
FROM    dbo.T1
WHERE   T1.ID IN (SELECT T2.ID FROM dbo.T2);

SELECT  T1.*
FROM    dbo.T1
        INNER JOIN dbo.T2
            ON T1.ID = T2.ID;

enter image description here

即使结果相同,执行计划也不是。使用IN的第一个查询能够使用反半连接,这意味着它知道不需要t2中的数据,所以一旦找到单个匹配,它就会停止扫描以进一步匹配。

如果您将第二个表限制为仅包含唯一值,那么您将看到相同的计划:

CREATE TABLE dbo.T1 (ID INT NOT NULL PRIMARY KEY);
INSERT dbo.T1 (ID) VALUES (1), (2), (3), (4), (5);

CREATE TABLE dbo.T2 (ID INT NOT NULL PRIMARY KEY);
INSERT dbo.T2 (ID) VALUES (1), (2), (3);

SELECT  *
FROM    dbo.T1
WHERE   T1.ID IN (SELECT T2.ID FROM dbo.T2);

SELECT  T1.*
FROM    dbo.T1
        INNER JOIN dbo.T2
            ON T1.ID = T2.ID;

enter image description here

总之,这两个查询不会总是产生相同的结果,并且它们并不总是具有相同的计划。这实际上取决于您的索引和数据/查询的宽度。