简体   繁体   中英

SQL Server Select alias with IN statement not working

I have the following SELECT statement.

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

If I execute that script, it returns NULL . However, if I remove the t. alias as below, it runs normally.

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

I find this quite strange. Any ideas?

You need to remove

AND s.SpareID = t.SpareID

from your sub query. You're using the subquery to filter the values of SpareID in the main query when SpareID doesn't yet have a value.

By the way, you can rewrite this query without the join, using window functions instead:

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

The reason you need the alias is because unaliased columns in a subquery are assigned to the table at the nearest reference. So,

 where s.SpareID = t.SpareID

compares the SpareId from the outer table reference to the inner one.

 where s.SpareID = SpareID

First determines which table SpareID comes from. It matches a column in the inner subquery, so it uses that. The expression is equivalent to:

where s.SpareID = s.SpareId

And finally, the user of convert with count is totally unnecessary. Count is just counting the number of non-NULL values, and this does not change when converting to a string.

For instance, when I test this code, it works fine:

declare @t uniqueidentifier = newid();

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

Although, interestingly, this code doesn't work on SQLFiddle. But there is is giving the error that @t is undefined, which is unrelated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM