Как избежать перехода между упорядоченной обработкой данных по столбцам и упорядоченной обработкой данных - PullRequest
1 голос
/ 20 февраля 2020

Я работаю над DB2 Blu с таблицами, организованными по столбцам.

Мой набор данных выглядит следующим образом:

Day month year value
------- -------
20200101 202001 2020 100
20200102 202001 2020 110
...
20200215 202002 2020 120

Я хочу агрегировать по неделям, месяцам и годам для этого результата :

Id value
2020 12000
202001 4000 'january
202002 4000 'february
2020001 700 'first week of 2020

Для этого у меня также есть таблица d_tps

Type Id week month year
J 20200101 2020001 202001 2020
J 20200102 2020001 202001 2020
...

J 20200215 2020007 202002 2020
M 202001 null 202001 2020
M 202002 null 202002 2020
Y 2020 null null 2020

Мой подход заключается в следующем

select d.id, sum(value) from tab1
Inner join d_tps d
On d.id = tab1.year
Or d.id = tab1.month
Or d.id = tab1.year
group by d.id

Он работает и возвращает ожидаемый результат. К сожалению, в плане запроса условие соединения с OR приводит к тому, что оператор CTQ приходит раньше, и большая часть запроса (который в действительности является более сложным) обрабатывается как строки, а не столбцы.

Как я могу его оптимизировать?

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

Вы должны использовать функцию GROUP BY GROUPING SETS & GROUPING, чтобы достичь того, что вы хотите.

WITH T (day, month, year, value) AS 
(
values 
  (20200101, 202001, 2020, 100)
, (20200102, 202001, 2020, 110)
, (20200215, 202002, 2020, 120)
)
SELECT 
CASE 
  WHEN GROUPING(DAY)   = 0 THEN DAY
  WHEN GROUPING(MONTH) = 0 THEN MONTH
  WHEN GROUPING(YEAR ) = 0 THEN YEAR
END AS ID
, SUM(VALUE) AS VALUE
FROM T
GROUP BY GROUPING SETS (DAY, MONTH, YEAR);

Результат:

|ID         |VALUE      |
|-----------|-----------|
|2020       |330        |
|202001     |210        |
|202002     |120        |
|20200101   |100        |
|20200102   |110        |
|20200215   |120        |
1 голос
/ 20 февраля 2020

Похоже, одного условия join достаточно для агрегации:

select d.week, sum(value)
from tab1 Inner join
     d_tps d
     On d.id = tab1.day
group by d.week

Если вы хотите агрегировать по нескольким временным уровням, используйте grouping sets:

select d.week, d.month, d.year, sum(value)
from tab1 Inner join
     d_tps d
     On d.id = tab1.day
group by grouping sets ((d.week), (d.month), (d.year))
...