Как рассчитать скользящую сумму со сбросом на основе условия в teradata SQL?

У меня есть эти данные, и я хочу суммировать поле USAGE_FLAG, но сбрасываю его, когда оно падает до 0 или переходит к новому идентификатору, сохраняя набор данных, упорядоченный по SU_ID и WEEK:

SU_ID   WEEK    USAGE_FLAG
100        1    0
100        2    7
100        3    7
100        4    0
101        1    0
101        2    7
101        3    0
101        4    7
102        1    7
102        2    7
102        3    7
102        4    0

Итак, я хочу создать эту таблицу:

SU_ID   WEEK    USAGE_FLAG    SUM
100        1    0             0
100        2    7             7
100        3    7             14
100        4    0             0
101        1    0             0
101        2    7             7
101        3    0             0
101        4    7             7
102        1    7             7
102        2    7             14
102        3    7             21
102        4    0             0

Я пробовал использовать функцию MSUM(), используя GROUP BY, но она не соблюдает порядок, который я хочу выше. Он группирует 7 и номера недель вместе, что мне не нужно.

Кто-нибудь знает, возможно ли это сделать? Я использую терадату


person wilsonm2    schedule 11.12.2012    source источник
comment
Ура, bluefeet, как ты редактировал это как таблицу?   -  person wilsonm2    schedule 11.12.2012


Ответы (3)


В стандартном SQL текущая сумма может быть сделана с помощью оконной функции:

select su_id,
       week,
       usage_flag, 
       sum(usage_flag) over (partition by su_id order by week) as running_sum
from the_table;

Я знаю, что Teradata поддерживает оконные функции, но я просто не знаю, поддерживает ли она также порядок в определении окна.

Сбросить сумму немного сложнее. Сначала вам нужно создать «идентификаторы групп», которые меняются каждый раз, когда usage_flag становится 0. Следующее работает в PostgreSQL, я не знаю, работает ли это и в Teradata:

select su_id,
       week,
       usage_flag,
       sum(usage_flag) over (partition by su_id, group_nr order by week) as running_sum
from (
  select t1.*,
         sum(group_flag) over (partition by su_id order by week) as group_nr
  from (
      select *,
             case
                when usage_flag = 0 then 1
                else 0
              end as group_flag
      from the_table
  ) t1
) t2
order by su_id, week;
person a_horse_with_no_name    schedule 11.12.2012
comment
Спасибо, это работает, как при создании моей желаемой таблицы? Я пробовал это в терадате, но он показывает общую сумму на группу su_id. - person wilsonm2; 11.12.2012
comment
@ wilsonm2: я не знаю, чем отличается Teradata, но приведенное выше возвращает именно то, что вы хотите в PostgreSQL: sqlfiddle.com / #! 12 / 2046f / 1 и Oracle: sqlfiddle. ru / #! 4 / ee6a1 / 2 - person a_horse_with_no_name; 11.12.2012
comment
Так и есть, спасибо! Я собираюсь попробовать поиграть с ним в терадате и посмотреть, в чем разница. - person wilsonm2; 11.12.2012

Попробуйте приведенный ниже код, с использованием функции RESET он работает нормально.

select su_id,
       week,
       usage_flag, 
       SUM(usage_flag) OVER (
        PARTITION BY su_id
        ORDER BY week
        RESET WHEN usage_flag < /* preceding row */ SUM(usage_flag) OVER (
             PARTITION BY su_id ORDER BY week
             ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING)
        ROWS UNBOUNDED PRECEDING
   )
from emp_su;
person Amit Kumar Sethiya    schedule 19.06.2014

Пожалуйста, попробуйте ниже SQL:

select su_id,
       week,
       usage_flag, 
       SUM(usage_flag) OVER (PARTITION BY su_id ORDER BY week
        RESET WHEN usage_flag = 0 
        ROWS UNBOUNDED PRECEDING
   )
from emp_su;

Здесь RESET WHEN usage_flag = 0 будет сбрасывать сумму, когда сумма usage_flag упадет до 0

person Rohit Khattri    schedule 06.07.2017