объединить набор статусов строк в единый итоговый статус

#sql #oracle #aggregate-functions

#sql #Oracle #агрегатные функции

Вопрос:

У меня есть представление, которое выглядит следующим образом:

 package_id  package_line  status_a        status_b
1           1             NOT_STARTED     FAILED
1           2             STARTED         STARTED
1           3             FAILED          NOT_STARTED
2           1             COMPLETE        STARTED
2           2             COMPLETE        NOT_STARTED
  

и так далее, для нескольких тысяч строк. Status_a и status_b — это отдельные, не связанные между собой статусы (фактически они зависят от того, выполняется ли пакет в системе a или в системе b).

Мне нужна сводка по package_id, чтобы свести к

    package_id status_a  status_b
   1          FAILED    FAILED
   2          COMPLETE  NOT_STARTED
  

Правила объединения строк пакета следующие

  1. If any package line has failed, the package has failed.
 2. If all package lines are complete, the package is complete.
 3. If all package lines are NOT_STARTED, the package has not started.
 4. Otherwise, the package is started (i.e. a combination of started, not_started, and complete would summarize as STARTED).
  

Итак, я пытаюсь придумать запрос для создания этого резюме. Я бы хотел опубликовать пример кода, но я действительно в растерянности. Предположительно, я хочу сгруппировать по package_id, но что я могу использовать в качестве агрегатной функции, которая позволила бы мне применять перечисленные правила?

Если это поможет, у меня есть контроль над тем, как отображаются статусы на уровне строки пакета, поэтому я мог бы сообщить числовой статус (хотя мне нравится, чтобы он был доступен для чтения человеком просто для удобства).

Ответ №1:

Попробуйте это (то же самое для status_b ):

 SELECT package_id,
       CASE WHEN FAILED_COUNT > 0 THEN 'FAILED'
            WHEN COMPLETE_COUNT = ALL_COUNT THEN 'COMPLETE'
            WHEN NOT_STARTED_COUNT = ALL_COUNT THEN 'NOT_STARTED'
            ELSE 'STARTED'
       END status_a
FROM (            
SELECT package_id,
     COUNT(status_a) ALL_COUNT,
     SUM(CASE WHEN status_a = 'FAILED' THEN 1 ELSE 0 END) FAILED_COUNT,
     SUM(CASE WHEN status_a = 'COMPLETE' THEN 1 ELSE 0 END) COMPLETE_COUNT,
     SUM(CASE WHEN status_a = 'NOT_STARTED' THEN 1 ELSE 0 END) NOT_STARTED_COUNT,
     SUM(CASE WHEN status_a = 'STARTED' THEN 1 ELSE 0 END) STARTED_COUNT
 FROM table
GROUP BY package_id
)
  

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

1. Отлично, спасибо! Исправлена пара неуместных запятых на случай, если кто-нибудь еще захочет однажды использовать это.