Ранжирование по нескольким столбцам

#sql #optimization #partition

#sql #оптимизация #перегородка

Вопрос:

В процессе оптимизации запросов я добрался до следующего SQL-запроса:

 select s.*
from
(
select id, DATA, update_dt, inspection_dt, check_dt
RANK OVER() 
(PARTITION by ID
 ORDER BY update_dt DESC, DATA) rank
 FROM TABLE 
where update_dt < inspection_dt or update_dt < check_dt 
) r
where r.rank = 1
 

Запрос возвращает ДАННЫЕ, соответствующие последнему check_dt.
Однако то, что я хочу получить, это:
1. ДАННЫЕ, соответствующие последнему check_dt
2. ДАННЫЕ, соответствующие последнему inspection_dt.

Одно из тривиальных решений — просто напишите два отдельных запроса с единственным условием where — один для inspection_dt и один для check_dt. Однако таким образом теряется первоначальное намерение — сократить время выполнения.

Наблюдая за исходными данными, я заметил способ его реализации — дата проверки всегда позже даты проверки; зная, что я мог бы просто извлечь запись с рангом = 1, и она даст мне ДАННЫЕ, соответствующие последнему CHECK_DT, а запись с наибольшим рангом будет соответствовать ПРОВЕРКЕ. Однако, боюсь, данные не всегда будут согласованными, поэтому я искал более абстрактное решение.

Ответ №1:

Как насчет этого?

 select s.*
from (select id, DATA, update_dt, inspection_dt, check_dt,
             RANK() OVER (PARTITION by ID
                          ORDER BY update_dt DESC, DATA
                         ) as rank_upd,
             RANK() OVER (PARTITION by ID
                          ORDER BY inspection_dt DESC, DATA
                         ) as rank_insp,

     FROM TABLE 
    ) r
where r.rank_upd = 1 or r.rank_insp = 1;