Лучший способ добиться разрыва C или передачи Python в выражении case SQL?

Учитывая выражение SQL CASE с вложенными выражениями CASE, я ищу лучший способ эмулировать разрыв C или передачу Python во вложенном выражении CASE, чтобы я мог оценить остальные внешние варианты WHEN.

Например, представьте

select CASE 
         WHEN C1 THEN CASE
                      WHEN CA THEN 100
                      WHEN CB THEN 200
                     -- implied ELSE NULL
                     END
         WHEN C2 THEN CASE
                      WHEN CC THEN 300
                      WHEN CD THEN 400
                      ELSE 500
                     END
         WHEN C3 THEN CASE
                      WHEN CE THEN 600
                     END
         WHEN C4
... etc

предположим, что оба условия C1 и C3 истинны, а C2 и C4 ложны. также предположим, что CA и CB ложны, CE истинны.

Внутренний случай для C1 принимает подразумеваемый ELSE NULL. Я хотел бы функционально иметь возможность сказать ELSE BREAK и позволить C2, C3 и т. д. оцениваться как часть внешнего случая. Желаемый результат 600.

Лучший способ, который я нашел, - это заменить внешний корпус ОБЪЕДИНЕНИЕМ всех внутренних корпусов.

такие как

COALESCE(
           CASE C1 THEN
           CASE
                WHEN CA THEN 100
                WHEN CB THEN 200
           END
           END
           ,
           CASE C2 THEN
           CASE
                WHEN CC THEN 300
                WHEN CD THEN 400
                ELSE 500
           END
           END
           ,
           CASE C3 THEN
           CASE
                WHEN CE THEN 600
           END
           END
          ,
... etc   )

У кого-нибудь есть другие идеи? С несколькими уровнями CASE исходный код увеличивается в размере, что затрудняет его поддержку.

Я использую стандартный SQL 2008, никаких расширений, которые можно найти в T/SQL или SQL/PLUS и т. д.

Может быть, у вас есть способ отформатировать мое решение, чтобы сделать его наиболее читабельным?

Спасибо.


person Gary Gilbert    schedule 05.11.2011    source источник


Ответы (2)


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

 Row C1  C2  C3  CA  CB  CC CD CE Value
 1   T   F   F   T   F   F  F  F  100
 2   T   F   F   F   T   F  F  F  200
 3   F   T   F   F   T   F  F  F  300
 4   F   T   F   F   F   F  T  F  400
 5   F   T   F   T   F   T  F  T  500
 6   F   F   T   F   F   F  F  T  600
 ....

Тогда ваш оператор sql будет выглядеть так

 SELECT l.[value]
 FROM table t
 JOIN lookup l ON (t.C1 = l.C1 AND t.C2 = l.C2 AND t.C3 = l.C3)
              AND (t.CA = l.CA 
                OR t.CB = l.CB 
                OR t.CC = l.CC 
                OR t.CD = l.CD
                OR t.CE = l.CE)

Я считаю, что это логика, которая вам нужна для вашего внутреннего и вашего внешнего.

Обратите внимание на строку 5, потому что последние 5 объединяются по ИЛИ в соединении, это позволит поиску действовать как ELSE во внутренних случаях.

Вы могли бы просто иметь все и в соединении и "полную" таблицу поиска - это может быть проще для отладки и работы.

person Hogan    schedule 05.11.2011
comment
Я упростил проблему, когда задал исходный вопрос. В реальной проблеме, которую я решаю, значения в предложениях WHEN являются выражениями, которые ссылаются на 1 или несколько дополнительных столбцов, поэтому соединение со второй таблицей для меня не работает. Я вижу, как предложенный вами шаблон соединения будет действительно полезен в других ситуациях. Спасибо. - person Gary Gilbert; 06.11.2011
comment
@GaryGilbert - соединения могут включать выражения, этот метод все еще может работать. - person Hogan; 06.11.2011

Один из способов:

select CASE 
         WHEN C1 AND CA THEN 100
         WHEN C1 AND CB THEN 200
                     --- simulated BREAK
         WHEN C2 THEN CASE
                      WHEN CC THEN 300
                      WHEN CD THEN 400
                      ELSE 500
                     END
         WHEN C3 AND CE THEN 600
                     --- simulated BREAK
         WHEN C4
... etc
person ypercubeᵀᴹ    schedule 05.11.2011
comment
Иногда работает сглаживание выражения встроенного корпуса только с внешним корпусом. Я думаю, что это может затруднить поддержку конечного запроса. Комментарии и отступы могут помочь. Проблема, которую я решаю, имеет около дюжины предложений WHEN внешнего случая, многие из которых имеют внутренние случаи с 5-8 предложениями WHEN. Сведение его к одному регистру означает, что может быть 60 предложений WHEN, многие из которых повторяют внутренние выражения WHEN. Проблема усугубится, если выражение CASE будет вложено более чем в 2 раза. Они радости декларативного непрограммного языка. :) - person Gary Gilbert; 06.11.2011
comment
@GaryGilbert: да, для сложных вложенных CASE подход Хогана кажется более подходящим. Я бы тоже это использовал. - person ypercubeᵀᴹ; 06.11.2011