Выражение CASE в предложении WHERE с двумя значениями

#sql #sql-server

#sql #sql-сервер

Вопрос:

Я пытался написать запрос для извлечения данных из таблицы при условии, что предложение where имеет регистр, но мне нужно поместить or в оператор case, но я не могу найти решение:

Ниже приведен мой запрос

 SELECT WFET.InstanceID,
       WFI.SomeID
FROM [SOME_Instance] WFI
     INNER JOIN [SomeTracker] WFET ON WFI.InstanceID = WFET.InstanceID
     INNER JOIN SOMEPROP_INSTANCE WFPI ON WFET.ItemID = WFPI.WIID
WHERE WFI.InstanceID NOT IN (SELECT WFTT.InstanceID
                             FROM [SomeTracker] WFTT
                                  INNER JOIN [dbo].[SomeItems_Instance] WFII ON WFII.ITemID = WFTT.ItemID
                                  INNER JOIN SomeActivities WFA ON WFII.ActivityType = WFA.ActivityTypeID
                             WHERE WFTT.Status IN (CASE WHEN WFA.ActivityType <> 'Conn' THEN ('Running','Pending') ELSE 'Pending' END))
  AND WFI.Status = 'Running'
  AND WFPI.PropertyType <> 'Last'
GROUP BY WFET.InstanceID,
         WFI.SomeID;
  

Комментарии:

1. Это выражение case, то есть оно возвращает одно атомарное значение. Таким образом, вы не можете использовать его таким образом.

2. Пожалуйста, также не КРИЧИТЕ; мы прекрасно можем прочитать ваши внутренние слова.

3. хорошо, но есть ли какой-либо способ, с помощью которого я могу организовать свой запрос так, чтобы я мог указать два значения

4. SQL с выравниванием по левому краю так сложно читать и писать.

5. CASE Выражение возвращает скалярное значение. THEN ('Running','Pending') не имеет смысла, поскольку это список значений. THEN Может возвращать только 1 значение, а не много.

Ответ №1:

Вы можете упростить where логику до:

 WHERE WFTT.Status = 'Pending' OR
      (WFA.ActivityType <> 'Conn' AND WFIT.Status = 'Running')
  

Ответ №2:

Перефразируйте предложение where в подзапросе как:

 WHERE
     (WFA.ActivityType <> 'Conn' AND WFTT.Status IN ('Running','Pending')) OR
      WFA.ActivityType = 'Conn' AND WFTT.Status = 'Pending'
  

Ваше использование CASE выражений было неправильным, поскольку они должны генерировать одно скалярное значение. CASE Выражение не может сгенерировать кортеж, но мы все равно можем выразить нужную вам логику.

Полный код:

 WHERE WFI.InstanceID NOT IN (SELECT WFTT.InstanceID
                             FROM [SomeTracker] WFTT
                             INNER JOIN [dbo].[SomeItems_Instance] WFII
                                 ON WFII.ITemID = WFTT.ItemID
                             INNER JOIN SomeActivities WFA
                                 ON WFII.ActivityType = WFA.ActivityTypeID
                             WHERE
                                 WFA.ActivityType <> 'Conn' AND
                                 WFTT.Status IN ('Running','Pending') OR
                                 WFA.ActivityType = 'Conn' AND
                                 WFTT.Status = 'Pending')
  

Ответ №3:

CASE Выражение возвращает одно значение в зависимости от логических выражений. Оно не может вернуть кортеж. И мы обычно не используем CASE в WHERE предложении в любом случае, потому WHERE что само предложение генерирует логическое значение. Вместо этого мы используем AND и OR для описания желаемых ограничений.

Ваше выражение

 WHERE WFTT.Status IN (CASE WHEN WFA.ActivityType <> 'Conn'
                           THEN ('Running','Pending') ELSE 'Pending' END))
  

будет записано как

 WHERE WFTT.Status = 'Pending'
   OR (WFA.ActivityType <> 'Conn' AND WFTT.Status = 'Running')