Страницы

Поиск по вопросам

среда, 4 марта 2020 г.

Группировка с зависимой максимизацией двух столбцов (без подзапросов)

#sql #oracle #plsql


Есть задача вывести все строки, группируя таблицу по столбцу 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 

    


Ответы

Ответ 1



Да, оконными функциями делается элементарно: 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).

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

Отправить комментарий