这两个查询作为获得两个不同的结果集有什么区别?

问题描述 投票:3回答:6

我为这两个查询获得了不同的结果集,第二个结果集似乎是正确的。这些查询有什么区别。

内部连接查询秒是什么类型?

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
sql sql-server tsql sql-server-2005
6个回答
8
投票

当您在INNER JOIN中执行此操作时,实际上没有什么区别。

但是,当您将附加过滤器放入JOIN或WHERE子句中时,使用LEFT或RIGHT JOIN会有所不同[]。将过滤器放入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

请注意注释中指示的不同结果。

这些查询应该返回相同的结果。请发布完整的查询。

下面是一个示例,展示了来自两个变体的相同输出:

样本:

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子句中的谓词进行了评估。
  1. 来自T2的所有不匹配的行都被添加回T3列值的NULL值。
  2. WHERE子句被应用。
  3. 在步骤2中添加回的所有这些行中的任何一个都不会在步骤3中满足T3.col = somevalue谓词,因为我们知道所有这些行的此列的值为NULL

SQL是一种声明性语言,由DBMS来实现您的查询。 SQL Server查询优化器不在乎是否使用JOIN表达式,WHERE表达式,IN表达式或EXISTS表达式内部联接两个表,在内部它们都被视为相同。 SQL Server有3种不同的内部联接算法,它们仅根据行数和数据分布来选择,而不是用来声明它们的确切语法。如果在示例中比较两个查询的执行计划,您应该发现它们是相同的,因此将产生相同的结果集。

不同之处在于,在所有联接之后都将访问WHERE子句。

这意味着在这种情况下可能没有区别,但是当存在多个联接时,这并不总是正确的。在处理WHERE之前,可以将它们从虚拟结果集中剔除(取决于情况)。

请查看此链接:http://blog.sqlauthority.com/2009/04/06/sql-server-logical-query-processing-phases-order-of-statement-execution/

我相信是这样的:

第一个查询从联接的表中获取所有结果,然后对WHERE子句进行过滤。

第二个查询从状态ID = 12的表1获得结果,然后对结果集执行联接。

有细微的差别。

编辑:这是验证差异的文章的链接:http://www.sqlteam.com/article/additional-criteria-in-the-join-clause


7
投票
这些查询应该返回相同的结果。请发布完整的查询。

3
投票
查看问题的编辑历史记录,您的查询似乎遵循以下几行。

1
投票
SQL是一种声明性语言,由DBMS来实现您的查询。 SQL Server查询优化器不在乎是否使用JOIN表达式,WHERE表达式,IN表达式或EXISTS表达式内部联接两个表,在内部它们都被视为相同。 SQL Server有3种不同的内部联接算法,它们仅根据行数和数据分布来选择,而不是用来声明它们的确切语法。如果在示例中比较两个查询的执行计划,您应该发现它们是相同的,因此将产生相同的结果集。

0
投票
不同之处在于,在所有联接之后都将访问WHERE子句。

这意味着在这种情况下可能没有区别,但是当存在多个联接时,这并不总是正确的。在处理WHERE之前,可以将它们从虚拟结果集中剔除(取决于情况)。


-1
投票
我相信是这样的:

第一个查询从联接的表中获取所有结果,然后对WHERE子句进行过滤。

© www.soinside.com 2019 - 2024. All rights reserved.