Функция ранжирования со сложным сценарием

#sql #rank #dense-rank #analytical

#sql #ранжирование #плотный ранг #аналитический

Вопрос:

введите описание изображения здесь

У меня есть таблица TABLE1 и столбцы, такие как ID, Status и Code

В зависимости от приоритета кода, который я хочу получить, приоритет равен

SS -> RR -> TT -> AA (этот приоритет не сохраняется ни в каких таблицах)

Запрос должен сначала искать утвержденный статус, затем нам нужно проверить столбец кода Example1: ID: 2345 — эта запись, имеющая утвержденный статус для всех кодов, таких как SS, AA и RR, и на основе приоритета кода SS должна быть выведена на выходе как 2345, SS

Пример2: ID: 3333 — Эта запись, имеющая статус утверждения для всех кодов, таких как RR и TT, и основанная на приоритете кода RR, должна быть извлечена в выходных данных как 3333, RR

ID: 4444 — Несмотря на то, что эта запись содержит такие коды, как SS и RR, но в столбце статуса указано значение, поэтому нам нужно заполнить следующий приоритет в списке, и вывод должен отображаться как 4444 TT

ИДЕНТИФИКАТОР: 5555- Ни один из статусов для этого идентификатора не имеет утвержденного статуса, все имеют статус, обозначенный как so, на основе приоритета в выводе 5555, SS должен быть выбран, поскольку этот является приоритетом

таким образом, выходные данные для 2345 и 5555 одинаковы, только разница в том, что если ни одна из записей не имеет утвержденного статуса, то только мы должны перейти к Termed — если запись имеет только termed, то на основе приоритетной записи должна быть извлечена

Приложил картинку для справки

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

1. Пометьте свой вопрос базой данных, которую вы используете.

Ответ №1:

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

 WITH cte AS (
    SELECT t.*,
           RANK() OVER (PARTITION BY ID
                        ORDER BY CASE Status WHEN 'Approved' THEN 1
                                             WHEN 'Termed'   THEN 2
                                             ELSE 3 END,
                                 CASE Code WHEN 'SS' THEN 1
                                           WHEN 'RR' THEN 2
                                           WHEN 'TT' THEN 3
                                           WHEN 'AA' THEN 4 END) rnk
    FROM yourTable t
    WHERE Status = 'Approved'
)

SELECT ID, Code
FROM cte
WHERE rnk = 1;
 


ДЕМОНСТРАЦИЯ

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

1. если идентификатор имеет как статус «ПОДТВЕРЖДЕНО», так и статус «ОДОБРЕНО», тогда мы должны проверить «одобрено» и получить запись на основе приоритета — если идентификатор имеет только статус «УКАЗАНО» для всех кодов, то на основе вывода pirority следует заполнить, например, Example4: ID: 5555 — эта запись, имеющая статус «УКАЗАНО» длявсе коды, такие как RR и TT, и основанные на приоритете кода RR, должны быть выведены на выходе как 5555, RR

2. Отредактируйте свой вопрос и предоставьте примеры данных, объясняющих это новое требование.

3. @Ram я отредактировал с учетом того, что, по моему мнению, является вашей желаемой логикой. Я только добавил второй уровень сортировки в ORDER BY предложение of RANK .

4. это не работает, если идентификатор имеет оба статуса, например «ОДОБРЕН» или «ОПРЕДЕЛЕН» — поскольку мое требование заключается в том, что первый запрос должен искать статус Утвержден … если запись не имеет какого-либо определенного статуса, то в этом статусе запись статуса должна основываться на записи приоритета, которая должна быть извлечена — дайте мне знатьесли вам нужна дополнительная информация

Ответ №2:

 create table table1 (id, status, code) as
select 2345, 'Approved', 'SS' from dual union all
select 2345, 'Approved', 'AA' from dual union all
select 2345, 'Approved', 'RR' from dual union all
select 3333, 'Approved', 'RR' from dual union all
select 3333, 'Approved', 'TT' from dual union all
select 4444, 'TERMED', 'SS' from dual union all
select 4444, 'TERMED', 'RR' from dual union all
select 4444, 'Approved', 'TT' from dual
;

select ID, CODE
from (
  select ID, STATUS, CODE
    , row_number()over( 
            partition by ID 
            order by status
                     , decode(code, 'SS', 1, 'RR', 2, 'TT', 3, 'AA', 4) ) rank
  from table1
)
where rank = 1
;