Есть задача вывести все строки, группируя таблицу по столбцу t_name, при этом максимизируя по двум столбцам t_date и t_num, так что
вначале максимизируя по столбцу t_num
затем оставшаяся выборка максимизируется по t_date
Вопрос: можно ли это организовать без подзапросов (например, оконными функциями или другими способами), и будет ли это работать быстрее?
Для примера
t_name t_date t_num
1 aaa 20.01.2018 3
2 aaa 03.01.2018 10
3 aaa 01.01.2018 10
4 aaa (null) 10
5 bbb 19.01.2018 1
6 bbb (null) 10
в результате максимизации по столбцу t_num останутся значения
t_name t_date t_num
2 aaa 03.01.2018 10
3 aaa 01.01.2018 10
4 aaa (null) 10
6 bbb (null) 10
затем выборку максимизируется по столбцу t_date и останутся значения
t_name t_date t_num
2 aaa 03.01.2018 10
6 bbb (null) 10
Это легко можно сделать через подзапросы
SELECT
T.T_NAME,
MAX(T.T_DATE) AS T_DATE,
G.T_NUM
FROM
TEST_GROUPING T
INNER JOIN (
SELECT T_NAME, MAX(T_NUM) AS T_NUM
FROM TEST_GROUPING
GROUP BY T_NAME
) G ON G.T_NAME = T.T_NAME AND G.T_NUM = T.T_NUM
GROUP BY
T.T_NAME,
G.T_NUM
Ответ
Да, оконными функциями делается элементарно:
with t (t_name, t_date, t_num) as (
select 'aaa', to_date('20.01.2018', 'dd.mm.yyyy'), 3 from dual union all
select 'aaa', to_date('03.01.2018', 'dd.mm.yyyy'), 10 from dual union all
select 'aaa', to_date('01.01.2018', 'dd.mm.yyyy'), 10 from dual union all
select 'aaa', null, 10 from dual union all
select 'bbb', to_date('20.01.2018', 'dd.mm.yyyy'), 1 from dual union all
select 'bbb', null, 10 from dual)
select t_name, t_date, t_num
from (select t_name, t_date, t_num,
row_number() over (partition by t_name order by t_num desc, t_date desc nulls last) rn
from t)
where rn = 1
Работать тоже должно быстро, особенно если у вас есть индекс по t_num, а лучше даже по (t_num, t_date).
Комментариев нет:
Отправить комментарий