我为这两个查询得到不同的结果集,第二个结果集似乎是正确的。这些查询有什么不同。
第二种是什么类型的内连接查询?
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
答案 0 :(得分:8)
在INNER JOIN中执行此操作时,确实没有任何区别。
但是,当您使用LEFT或RIGHT JOIN时,无论是将其他过滤器放入JOIN还是WHERE子句,确实都会有所不同。
当您将过滤器放入WHERE子句时,SQL Server首先执行连接,然后完全过滤掉过滤器不适合的行。
- >这将减少返回的行数
当您将过滤器放入JOIN时,SQL Server会在连接期间执行过滤,但仅限于放置过滤器的表。
您仍然可以从其他表中获取所有行,但只有那些具有过滤器适合的过滤表中的数据
- >这不会减少行数,但是包含filteres表数据的列在更多行中将为空
很难解释......为了更清楚,这是一个例子:
从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
请注意评论中指出的不同结果。
答案 1 :(得分:7)
这些查询应返回相同的结果。请发布完整的查询。
以下是展示两种变体的相同输出的示例:
<强>示例:强>
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)
答案 2 :(得分:3)
查看问题的编辑历史记录,您的查询似乎是以下几行。
查询一个
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
...
它们之间的区别在于,查询一有效地将LEFT
加入转换为INNER
加入。
对于左外连接,概念上会发生以下情况。
步骤2中添加的这些行中没有一行符合步骤3中的T3.col = somevalue
谓词,因为我们知道所有这些行的此列的值为NULL
。
答案 3 :(得分:1)
SQL是一种声明性语言,由DBMS来实现您的查询。 SQL Server查询优化器不关心您是使用JOIN
表达式,WHERE
表达式,IN
表达式还是EXISTS
表达式内连接两个表,在内部它们都被对待了。 SQL Server有3种不同的内部连接算法,这些算法仅根据行数和数据分布选择,而不是用于声明它们的确切语法。如果比较示例中两个查询的执行计划,您应该发现它们是相同的,因此会生成相同的结果集。
答案 4 :(得分:0)
引擎盖下的区别在于在所有连接之后访问WHERE子句。
这意味着在这种情况下可能没有区别,但是当存在多个连接时,这并不总是正确的。在处理WHERE之前,可以将它们从虚拟结果集中分解出来(取决于具体情况)。
答案 5 :(得分:-1)
我相信它是这样的:
第一个查询从连接表中获取所有结果,然后对WHERE子句进行过滤。
第二个查询从表1中获取StatusID = 12的结果,然后对结果集执行连接。
这是一个微妙的区别。
编辑: 以下是验证差异的文章的链接: http://www.sqlteam.com/article/additional-criteria-in-the-join-clause