简体   繁体   中英

Invalid Column Name When Group By Nested Select

I have the following code, when I run it as is it will return to me the data I would like:

select tagid, 
  (select TOP 1 Locations.CostCenter
  from item
  inner join transactions on transactions.itemid = item.id 
  inner join recvlocationmapping on recvlocationid = transactions.locationid 
  left outer join locations on locations.id = servicelocationid  
  where tagid = c.TagID
  and costcenter != '' 
  and Costcenter is not null 
  order by transdate desc) as CostCenter
from item as c where createddate between '07-01-2012' and '07-05-2012' 

The problem comes when I want to add a group by to one of the columns. It then throws a error saying the column doesn't exist, but when I run the query without the Group By the column and name exist.

Here is the group by code that I'm having issues with:

select Count(tagid), 
  (select TOP 1 Locations.CostCenter
  from item
  inner join transactions on transactions.itemid = item.id 
  inner join recvlocationmapping on recvlocationid = transactions.locationid 
  left outer join locations on locations.id = servicelocationid  
  where tagid = c.TagID
  and costcenter != '' 
  and Costcenter is not null 
  order by transdate desc) as CostCenter
from item as c where createddate between '07-01-2012' and '07-05-2012'
group by CostCenter

I think it's an issue with how I'm returning the data, but I don't know enough about SQL to figure out how to fix it.

Aliases declared in select ... part cannot be used in group by . You either have to duplicate nested select in group by or use something like this:

select Count(q.tagid), q.CostCenter
from
    (select 
       tagid, 
       (select TOP 1 Locations.CostCenter
           from item
           inner join transactions on transactions.itemid = item.id 
           inner join recvlocationmapping on recvlocationid = transactions.locationid 
           left outer join locations on locations.id = servicelocationid  
           where tagid = c.TagID
           and costcenter != '' 
           and Costcenter is not null 
           order by transdate desc
       ) as CostCenter
       from item as c where createddate between '07-01-2012' and '07-05-2012'
    ) q
group by q.CostCenter

You can make use of the T-SQL APPLY functionality here, it is similar to the correlated subquery you have used but can be referenced multiple times without repeating the same code, and can also return multiple columns/rows if required.

SELECT  COUNT(tagid), 
        CostCenter
FROM    item as c 
        OUTER APPLY
        (   SELECT  TOP 1 Locations.CostCenter
            FROM    item
                    INNER JOIN transactions 
                        ON transactions.itemid = item.id 
                    INNER JOIN recvlocationmapping 
                        ON recvlocationid = transactions.locationid 
                    INNER JOIN locations 
                        ON locations.id = servicelocationid  
            WHERE   tagid = c.TagID
            AND     costcenter != '' 
            ORDER BY transdate DESC
        ) AS CostCenter
WHERE   createddate BETWEEN '07-01-2012' AND '07-05-2012'
GROUP BY CostCenter

I've also touched up a couple of things on your subquery, I changed the LEFT JOIN on locations to an INNER JOIN since you had AND CostCenter IS NOT NULL therefore a LEFT JOIN was not required and INNER JOIN s will perform better. Secondly AND CostCenter IS NOT NULL was redundant following AND CostCenter != '' because NULL != ''

EDIT

Upon further thought I think you can remove the correlated subqueries from it completely and get the same result using JOINS . This should result in more efficient execution:

;WITH CostCenter AS
(   SELECT  TagID, CostCenter, ROW_NUMBER() OVER(PARTITION BY TagID ORDER BY TransDate DESC) AS RowNumber
    FROM    item
            INNER JOIN transactions 
                ON transactions.itemid = item.id 
            INNER JOIN recvlocationmapping 
                ON recvlocationid = transactions.locationid 
            INNER JOIN locations 
                ON locations.id = servicelocationid  
    WHERE   costcenter != '' 
)
SELECT  COUNT(TagID), CostCenter
FROM    Item
        INNER JOIN CostCenter
            ON Item.TagID = CostCenter.TagID
            AND RowNumber = 1
WHERE   createddate BETWEEN '07-01-2012' AND '07-05-2012'
GROUP BY CostCenter

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