Использование предиката IN с инструкциями CASE в предложении WHERE для SQL Server

Вот запрос 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

Но я пытаюсь использовать предикат IN в сочетании с CASE WHEN в предложении WHERE. Посмотрите на модифицированный запрос ниже:

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

Кажется, это не работает и продолжает выдавать мне синтаксическую ошибку:

Сообщение 156, уровень 15, состояние 1, строка 15
Неверный синтаксис рядом с ключевым словом "IN".

Любая помощь или руководство, чтобы указать, что мне не хватает? Я был бы очень признателен за любую помощь/советы. Большое спасибо,

Пранав


person SillyCoda    schedule 17.01.2013    source источник


Ответы (1)


Ты прав. Синтаксис не разрешен. Можешь попробовать:

((@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. Если да, то это должно быть частью теста.

Если вам действительно нужен оператор case в предложении where, вы можете сделать следующее:

(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'
person Gordon Linoff    schedule 17.01.2013
comment
Это работает ИДЕАЛЬНО! Большое спасибо Гордон!! Я в долгу перед тобой!! - person SillyCoda; 17.01.2013