我为这两个查询获得了不同的结果集,第二个结果集似乎是正确的。这些查询有什么区别。
内部连接查询秒是什么类型?
1)
FROM TABLE1 t1
INNER JOIN TABLE2 t2 ON t1.Id = t2.Id
WHERE
t1.StatusId = 12
2)
FROM TABLE1 t1
INNER JOIN TABLE2 t2 ON t1.Id = t2.Id
AND t1.StatusId = 12
当您在INNER JOIN中执行此操作时,实际上没有什么区别。
但是,当您将附加过滤器放入JOIN或WHERE子句中时,使用LEFT或RIGHT JOIN会有所不同[]。将过滤器放入WHERE子句时,SQL Server首先执行联接,然后 完全地
很难解释...为了更清楚,这是一个例子:
从RedFilter's answer中获取样本数据:
CREATE TABLE [dbo].[t1](
[ID] [int] NULL,
[StatusID] [int] NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[t2](
[ID] [int] NULL
) ON [PRIMARY]
INSERT INTO t1 (ID, StatusID) VALUES (1, 10)
INSERT INTO t1 (ID, StatusID) VALUES (2, 11)
INSERT INTO t1 (ID, StatusID) VALUES (3, 12)
INSERT INTO t1 (ID, StatusID) VALUES (4, 12)
INSERT INTO t2 (ID) VALUES (1)
INSERT INTO t2 (ID) VALUES (3)
INSERT INTO t2 (ID) VALUES (5)
...并对其运行以下查询:
/* this returns four rows, but only two will have data from the second table in the second column */ SELECT t1.ID, t2.ID FROM t1 LEFT JOIN t2 ON t1.Id = t2.Id /* this returns only one row: the one where t2.ID = 1 */ SELECT t1.ID, t2.ID FROM t1 LEFT JOIN t2 ON t1.Id = t2.Id WHERE t2.ID = 1 /* this returns four rows as in the first query, but only one row will have data in the second column: the one where t2.ID = 1 */ SELECT t1.ID, t2.ID FROM t1 LEFT JOIN t2 ON t1.Id = t2.Id AND t2.ID = 1
请注意注释中指示的不同结果。
下面是一个示例,展示了来自两个变体的相同输出:
样本:
CREATE TABLE [dbo].[t1](
[ID] [int] NULL,
[StatusID] [int] NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[t2](
[ID] [int] NULL
) ON [PRIMARY]
INSERT INTO t1 (ID, StatusID) VALUES (1, 10)
INSERT INTO t1 (ID, StatusID) VALUES (2, 11)
INSERT INTO t1 (ID, StatusID) VALUES (3, 12)
INSERT INTO t1 (ID, StatusID) VALUES (4, 12)
INSERT INTO t2 (ID) VALUES (1)
INSERT INTO t2 (ID) VALUES (3)
INSERT INTO t2 (ID) VALUES (5)
SELECT t1.ID, t1.StatusID
FROM t1
INNER JOIN t2 ON t1.Id = t2.Id
WHERE t1.StatusId = 12
SELECT t1.ID, t1.StatusID
FROM t1
INNER JOIN t2 ON t1.Id = t2.Id
AND t1.StatusId = 12
输出:
ID StatusID
----------- -----------
3 12
(1 row(s) affected)
ID StatusID
----------- -----------
3 12
(1 row(s) affected)
查看问题的编辑历史记录,您的查询似乎遵循以下几行。查询一个
INNER JOIN dbo.T2 ON ... LEFT OUTER JOIN dbo.T3 ON ... WHERE T3.col = somevalue AND ...
查询二
INNER JOIN dbo.T2 ON ... LEFT OUTER JOIN dbo.T3 ON ... AND T3.col = somevalue WHERE ...
它们之间的区别在于查询One有效地将LEFT
联接转换为INNER
联接。对于概念上的左外部连接,将发生以下情况。
[T2被连接到T3上,并且对join子句中的谓词进行了评估。
- 来自T2的所有不匹配的行都被添加回T3列值的NULL值。
- WHERE子句被应用。
- 在步骤2中添加回的所有这些行中的任何一个都不会在步骤3中满足
T3.col = somevalue
谓词,因为我们知道所有这些行的此列的值为NULL
。SQL是一种声明性语言,由DBMS来实现您的查询。 SQL Server查询优化器不在乎是否使用JOIN
表达式,WHERE
表达式,IN
表达式或EXISTS
表达式内部联接两个表,在内部它们都被视为相同。 SQL Server有3种不同的内部联接算法,它们仅根据行数和数据分布来选择,而不是用来声明它们的确切语法。如果在示例中比较两个查询的执行计划,您应该发现它们是相同的,因此将产生相同的结果集。不同之处在于,在所有联接之后都将访问WHERE子句。这意味着在这种情况下可能没有区别,但是当存在多个联接时,这并不总是正确的。在处理WHERE之前,可以将它们从虚拟结果集中剔除(取决于情况)。
我相信是这样的:第一个查询从联接的表中获取所有结果,然后对WHERE子句进行过滤。
第二个查询从状态ID = 12的表1获得结果,然后对结果集执行联接。
有细微的差别。
编辑:这是验证差异的文章的链接:http://www.sqlteam.com/article/additional-criteria-in-the-join-clause
JOIN
表达式,WHERE
表达式,IN
表达式或EXISTS
表达式内部联接两个表,在内部它们都被视为相同。 SQL Server有3种不同的内部联接算法,它们仅根据行数和数据分布来选择,而不是用来声明它们的确切语法。如果在示例中比较两个查询的执行计划,您应该发现它们是相同的,因此将产生相同的结果集。这意味着在这种情况下可能没有区别,但是当存在多个联接时,这并不总是正确的。在处理WHERE之前,可以将它们从虚拟结果集中剔除(取决于情况)。
第一个查询从联接的表中获取所有结果,然后对WHERE子句进行过滤。