SQL группировать по годам и показывать месяцы предыдущего года - PullRequest
0 голосов
/ 28 февраля 2020

В моей таблице 5 столбцов:

client manager year month value

, и я хотел бы повернуть его к таблице, где месяцы должны быть в столбцах:

client manager year m01 m02 m03 m04 m05 m06 m07 m08 m09 m10 m11 m12

Я знаю, что я Можно сделать это следующим образом:

select
client, 
manager, 
year,
sum(case when month = 1 the value else 0 end) m01, 
sum(case when month = 2 the value else 0 end) m02, 
sum(case when month = 3 the value else 0 end) m03, 
sum(case when month = 4 the value else 0 end) m04, 
sum(case when month = 5 the value else 0 end) m05, 
sum(case when month = 6 the value else 0 end) m06, 
sum(case when month = 7 the value else 0 end) m07, 
sum(case when month = 8 the value else 0 end) m08, 
sum(case when month = 9 the value else 0 end) m09, 
sum(case when month = 10 the value else 0 end) m10,
sum(case when month = 11 the value else 0 end) m11, 
sum(case when month = 12 the value else 0 end) m12
from t
group by
client, 
manager, 
year

Но для некоторых дополнительных вычислений я хочу добавить столбцы m0 и m13 в мою таблицу, где m0 - это 12-й месяц предыдущего года, а m13 - это 1-й месяц в следующем году.

Есть ли простой способ (без использования объединений, опережающих и запаздывающих функций) сделать это с простой группой?

Ответы [ 3 ]

2 голосов
/ 28 февраля 2020

Хотя это, безусловно, возможно, не существует «простого» способа, потому что одна строка в исходных данных должна быть в нескольких строках в наборе результатов.

Тем не менее, это кажется довольно простым:

with t as (
      < your query here >
     )
select t.*,
       lag(m12) over (partition by client, manager order by year) as m0,
       lead(m1) over (partition by client, manager order by year) as m13
from t;
1 голос
/ 28 февраля 2020

Вы можете объединиться (или объединиться) с данными JAN и DE C, скопированными в другие годы, но я сомневаюсь, что это будет быстрее, чем lead и lag:

select * 
  from (
    select client, manager, value, year, month from t 
    union all
    select client, manager, value, 
           case month when  1 then year - 1 
                      when 12 then year + 1 end, 
           case month when  1 then 13 
                      when 12 then  0 end
      from t where month in (1, 12))
  pivot (sum(value) for month in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13))
  order by client, manager, year

Демоверсия dbfiddle

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

Вы можете продублировать строки, которые являются первым (или последним) месяцем года, и назначить новый месяц 13 (или 0) предыдущего (или следующего) года; Вы можете сделать это, используя функцию DECODE или выражение CASE. Тогда вы можете поворачиваться:

SELECT *
FROM   (
  SELECT client,
         manager,
         year,
         month,
         value
  FROM   t
  UNION ALL
  SELECT client,
         manager,
         DECODE( month, 1, year - 1, 12, year + 1 ),
         DECODE( month, 1,       13, 12,        0 ),
         value
  FROM   t
  WHERE  month IN ( 1, 12 )
)
PIVOT( SUM( value ) FOR month IN (
  0 AS m0,
  1 AS m1,
  2 AS m2,
  3 AS m3,
  4 AS m4,
  5 AS m5,
  6 AS m6,
  7 AS m7,
  8 AS m8,
  9 AS m9,
  10 AS m10,
  11 AS m11,
  12 AS m12,
  13 AS m13
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...