具有“where in”的Select语句返回的行数多于子查询

时间:2013-07-19 18:16:56

标签: sql subquery sql-server-2012 where-in

今天我们发现了SQL Server 2012 SP1的一些奇怪行为。我们知道如何重现问题,但我们不确定是什么导致了这个问题。这是一个非常概括的例子:


假设您有一个数据库test,它有一个表table1,包含以下数据:

column1
-
1
2
3
4

您运行以下查询:

USE [test]

SELECT [column1]
FROM [test].[dbo].[table1]
WHERE [column1] IN
(SELECT TOP 5 [column1]
FROM [table1])

返回5行,正如预期的那样。现在运行以下查询:

USE [test]

SELECT [column1]
FROM [test].[dbo].[table1]
WHERE [column1] IN
(SELECT TOP 5 [test].[dbo].[table1].[column1]
FROM [table1])

这次返回10行,即使SELECT TOP 5 [test].[dbo].[table1].[column1] FROM [table1]返回5行。


看看执行计划,我可以看出服务器正在做一些不同的事情,但我不知道为什么。

解决方案似乎是确保我们没有原因而过于明确,但现在我们已经遇到过,我们希望确保没有人再次导致这种行为。

1 个答案:

答案 0 :(得分:1)

查询的上下文是产生差异的原因。

在以下查询中,第二个select语句实际上是从第一个表中选择一个列。

SELECT [column1]
FROM [test].[dbo].[table1]
WHERE [column1] IN
(SELECT TOP 5 [test].[dbo].[table1].[column1]
FROM [table1])

如果您为表格提供别名,您会注意到不同的结果:

SELECT [column1]
FROM [test].[dbo].[table1] table1A
WHERE [column1] IN
(SELECT TOP 5 [test].[dbo].[table1].[column1]
FROM [table1])

此外,当您单独运行查询SELECT TOP 5 [test].[dbo].[table1].[column1] FROM [table1]时,不会混淆您选择的是哪个表。

您的查询相当于:

Select column1 from table1
where column1 in 
(select column1)

只要另一个表返回行,您选择的值在子查询中总是等于它自己。 它非常像是在说 在添加到另一个集合时,将列值等于其自身的集合中的每个给出。只要另一个集合不为空,列值将始终等于它。