1

我有以下SELECT声明。

SELECT t.ID, 
       t.SiteID, 
       t.SpareID, 
       t.SpareLocationID, 
       t.Qty, 
       t.IsDefault
  FROM TrainingDB.dbo.LocationsPerSpare t
 WHERE t.SpareID IN
       (SELECT s.SpareID
          FROM TrainingDB.dbo.LocationsPerSpare s
         WHERE s.SpareLocationID = t.SpareLocationID
           AND s.SpareID = t.SpareID
         GROUP BY s.SpareID
        HAVING COUNT(CONVERT(VARCHAR(36), s.SpareID)) > 2)
 ORDER BY t.SpareID

如果我执行该脚本,它会返回NULL. 但是,如果我如下删除t.别名,它会正常运行。

SELECT ID, 
       SiteID, 
       SpareID, 
       SpareLocationID, 
       Qty, 
       IsDefault
  FROM TrainingDB.dbo.LocationsPerSpare 
 WHERE SpareID IN
       (SELECT s.SpareID
          FROM TrainingDB.dbo.LocationsPerSpare s
         WHERE s.SpareLocationID = SpareLocationID
           AND s.SpareID = SpareID
         GROUP BY s.SpareID
        HAVING COUNT(CONVERT(VARCHAR(36), s.SpareID)) > 2)
 ORDER BY SpareID

我觉得这很奇怪。有任何想法吗?

4

2 回答 2

1

你需要删除

AND s.SpareID = t.SpareID

从您的子查询中。当 SpareID 还没有值时,您正在使用子查询过滤主查询中 SpareID 的值。

于 2013-02-23T20:17:15.300 回答
0

顺便说一句,您可以在不使用连接的情况下重写此查询,而是使用窗口函数:

select lps.ID, lps.SiteID, lps.SpareID, lps.SpareLocationID, 
       lps.Qty, lps.IsDefault
from (select lps.*,
             count(*) over (partition by spareId) as SpareCnt
      from TrainingDB.dbo.LocationsPerSpare lps
     ) lps
where SpareCnt > 2

您需要别名的原因是因为子查询中的非别名列被分配给最近引用处的表。所以,

 where s.SpareID = t.SpareID

将外部表引用中的 SpareId 与内部表引用进行比较。

 where s.SpareID = SpareID

首先确定SpareID来自哪个表。它匹配内部子查询中的列,因此它使用它。表达式等价于:

where s.SpareID = s.SpareId

最后,convertwith的用户count是完全没有必要的。 Count只是计算非 NULL 值的数量,并且在转换为字符串时不会改变。

例如,当我测试这段代码时,它工作正常:

declare @t uniqueidentifier = newid();

select count(distinct t)
from (select @t as t) v

虽然有趣的是,这段代码在 SQLFiddle 上不起作用。但是存在@t未定义的错误,这是不相关的。

于 2013-02-23T21:53:30.223 回答