使用' IN' SQL Server的WHERE子句中带有CASE语句的谓词

时间:2013-01-17 17:14:20

标签: sql where case-when

这是一个非常正常的SQL查询:

DECLARE @IncludePTO AS CHAR
SET @IncludePTO = 'Y'

SELECT     
   HQCO.HQCo, HQCO.Name, PREH.PRDept, PREH.Craft, HRRM.PositionCode, PRTH.Employee, 
   PREH.LastName, PREH.FirstName, SUM(PRTH.Hours) AS Hrs
FROM PREH 
INNER JOIN HRRM ON PREH.PRCo = HRRM.HRCo AND PREH.Employee = HRRM.HRRef 
INNER JOIN PRTH ON PREH.PRCo = PRTH.PRCo AND PREH.Employee = PRTH.Employee 
INNER JOIN HQCO ON PRTH.PRCo = HQCO.HQCo
WHERE     
    (dbo.PRTH.PREndDate BETWEEN '1/1/2012 00:00:00' AND '1/1/2013 00:00:00')
    AND (PRGroup = 2)
    AND dbo.PRTH.EarnCode IN (1,3,8)
GROUP BY 
    HQCO.HQCo, HQCO.Name, PREH.PRDept, PREH.Craft, 
    HRRM.PositionCode, PRTH.Employee, PREH.LastName, PREH.FirstName

但是,我试图在WHERE子句中使用'IN'谓词和CASE WHEN。看看下面的修改后的查询:

DECLARE @IncludePTO AS CHAR
SET @IncludePTO = 'Y'

SELECT     
   HQCO.HQCo, HQCO.Name, PREH.PRDept, PREH.Craft, HRRM.PositionCode, PRTH.Employee, 
   PREH.LastName, PREH.FirstName, SUM(PRTH.Hours) AS Hrs
FROM PREH 
INNER JOIN HRRM ON PREH.PRCo = HRRM.HRCo AND PREH.Employee = HRRM.HRRef 
INNER JOIN PRTH ON PREH.PRCo = PRTH.PRCo AND PREH.Employee = PRTH.Employee 
INNER JOIN HQCO ON PRTH.PRCo = HQCO.HQCo
WHERE     
    (dbo.PRTH.PREndDate BETWEEN '1/1/2012 00:00:00' AND '1/1/2013 00:00:00')
    AND (PRTH.PRGroup = 2)
    AND 
       CASE WHEN @IncludePTO = 'Y' THEN dbo.PRTH.EarnCode IN (1,2,3,8,100,110,120,115)
            ELSE dbo.PRTH.EarnCode IN (1,2,3,8)
       END
GROUP BY 
    HQCO.HQCo, HQCO.Name, PREH.PRDept, PREH.Craft, HRRM.PositionCode, PRTH.Employee, 
    PREH.LastName, PREH.FirstName

它似乎不起作用并且一直给我一个语法错误:

  

Msg 156,Level 15,State 1,Line 15
  关键字“IN”附近的语法不正确。

指出我缺少什么的任何帮助或指导?我非常感谢任何帮助/提示..非常感谢,

Pranav

1 个答案:

答案 0 :(得分:3)

你是对的。不允许使用语法。你可以尝试:

((@IncludePTO = 'Y' and dbo.PRTH.EarnCode IN (1,2,3,8,100,110,120,115)) or
 (@IncludePTO <> 'Y' and dbo.PRTH.EarnCode IN (1,2,3,8))
)

这可以简化为:

(bo.PRTH.EarnCode IN (1,2,3,8) or (@IncludePTO <> 'Y' and dbo.PRTH.EarnCode IN (100,110,120,115))
)

这假设@IncludePTO永远不会为NULL。如果是这样,则必须参加测试。

如果确实想要where子句中的case语句,您可以这样做:

(CASE WHEN @IncludePTO = 'Y' and dbo.PRTH.EarnCode IN (1,2,3,8,100,110,120,115)
      then 'true'
      when @IncludePTO <> 'Y' and dbo.PRTH.EarnCode IN (1,2,3,8)
      then 'true'
      else 'false'
 end) = 'true'