Выполнение текущего подсчета несекционированных данных в Google bigquery

У меня есть данные, которые выглядят так, как показано ниже

Date  | Priority
----------------
01/01 | Low
02/01 | Low
03/01 | Low
04/01 | Med
05/01 | Med
06/01 | Low
07/01 | High
08/01 | High
09/01 | Med
...

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

Date  | Priority | Days in state
--------------------------------
01/01 | Low      | 3
02/01 | Low      | 2
03/01 | Low      | 1
04/01 | Med      | 2
05/01 | Med      | 1
06/01 | Low      | 1
07/01 | High     | 2
08/01 | High     | 1
09/01 | Med      | 1
...

Я изо всех сил пытаюсь сделать это, потому что я не могу разделить данные в их нынешнем виде. При разделении по приоритету учитывается каждое вхождение этого приоритета в истории, а не только текущее "окно".

Я использовал IF(LAG(priority) OVER(ORDER BY date) = priority,1,0) чтобы отмечать изменения, но я не могу понять, что делать дальше.

2 ответа

Решение

Это своего рода проблема разрывов и островков. Для ваших целей самый простой способ - вычесть последовательность и использовать оконные функции:

select t.*,
       row_number() over (partition by status, grp order by date date desc) as days_to_next_state
from (select t.*,
             date_add(date, interval - seqnum day) as grp
      from (select t.*,
                   row_number() over (partition by status, order by date) as seqnum
            from t
           ) t
     ) t

Ниже приведен стандартный SQL BigQuery.

#standardSQL
SELECT date, Priority, 
  1 + DATE_DIFF(MAX(date) OVER(PARTITION BY grp), date, DAY) Days_in_state
FROM (
  SELECT date, Priority, 
    COUNTIF(start_new_Priority) OVER(ORDER BY date)grp
  FROM (
    SELECT date, Priority, 
      IFNULL(Priority != LAG(Priority) OVER(ORDER BY date), TRUE) start_new_Priority
    FROM `project.dataset.table`
  )
)

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

Row date        Priority    Days_in_state    
1   2019-01-01  Low         3    
2   2019-01-02  Low         2    
3   2019-01-03  Low         1    
4   2019-01-04  Med         2    
5   2019-01-05  Med         1    
6   2019-01-06  Low         1    
7   2019-01-07  High        2    
8   2019-01-08  High        1    
9   2019-01-09  Med         1    
Другие вопросы по тегам