简体   繁体   中英

Access alias in CASE statement

I am trying to create a column called DateStartedStatus that utilizes a previously aliased column to compute its value. It should use CurrentStatus to output a value and an error is showing that says "Invalid column name 'CurrentStatus'". How can I access that alias in the below case statement?

SELECT p.[ID]
  ,p.[Name] as 'ProcurementName'
  ,p.[FundingDocumentNumber] as 'FundingDocumentNumber'
  ,p.[Status]
  ,p.[Comments] as 'Comments'
  ,p.[isSAVE]
  ,p.[InWorkDate]
  ,p.[RoutedDate]
  ,p.[FundsCertifiedDate]
  ,p.[AwardedDate]
  ,p.[TransactionType]
  ,p.[FNMSStatus]
  ,p.[Closed]
  ,p.[Archived]
  ,p.[Cancelled]
  ,(CASE
    WHEN p.[Status] = 'In Work' THEN 'Pending'
    ELSE p.[Status]
   END) as CurrentStatus
  ,(CASE
   WHEN CurrentStatus = 'Awarded' THEN p.AwardedDate <-- fails here CurrentStatus not a column
   END) as DateStartedStatus
  ,(SELECT SUM(TotalCost) 
  FROM ProcurementsRequestLineItems subprlis
  LEFT JOIN RequestLineItems subrli ON subprlis.RequestLineItemID = subrli.ID
  WHERE ProcurementID = p.ID) as TotalCost
FROM Procurements p
WHERE p.Closed = 0 AND p.Archived = 0;

Use a subquery as suggested by leftjoin, or move the CurrentStatus logic to a CTE. I prefer CTE as they are more legible to me, but I know many prefer a subquery as it is right in the middle of the code, and in a longer query or one with many CTE's that can be a more legible route.

WITH CurrentStatus
AS
(
SELECT
... -- at least one JOIN'able column back to the main query
,(CASE
    WHEN p.[Status] = 'In Work' THEN 'Pending'
    ELSE p.[Status]
   END) as CurrentStatus
FROM ...
)

Using subqueries like this

select ... CASE WHEN CurrentStatus ....
from
( --calculate Current_status here
select ....
    CASE
    WHEN p.[Status] = 'In Work' THEN 'Pending'
    ELSE p.[Status]
   END) as CurrentStatus 
   ...   
) s

Do not worry, subquery will not add computational complexity, optimizer will remove it if possible.

Another way is nested CASE expressions (query is not readable):

case when case ... some logic here ... end = 'Awarded'
     then ...
end

For SQL Server, I would use a CROSS APPLY instead of an subquery, because I prefer it for readability. For one-condition evaluation, I use IIF instead of CASE.

SELECT p.[ID], p.[Name] AS [ProcurementName], p.[FundingDocumentNumber] AS [FundingDocumentNumber],
    p.[Status], p.[Comments] AS [Comments], p.[isSAVE], p.[InWorkDate], p.[RoutedDate], p.[FundsCertifiedDate],
    p.[AwardedDate], p.[TransactionType], p.[FNMSStatus], p.Closed, p.[Archived], p.[Cancelled],
    cur.CurrentStatus, start.DateStartedStatus, tot.TotalCost
FROM Procurements AS p
CROSS APPLY (SELECT IIF(p.[Status] = 'In Work', 'Pending', p.[Status]) AS CurrentStatus) AS cur
CROSS APPLY (SELECT IIF(cur.CurrentStatus = 'Awarded', p.AwardedDate, null) AS DateStartedStatus) AS start
CROSS APPLY (
    SELECT SUM(TotalCost) AS name
    FROM ProcurementsRequestLineItems AS subprlis
    LEFT JOIN RequestLineItems AS subrli ON subprlis.RequestLineItemID = subrli.ID
    WHERE ProcurementID = p.ID
    ) AS tot
WHERE p.Closed = 0 AND p.Archived = 0;

I would also avoid using the reserved word "Status" as a column identifier.

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