Из таблицы изменений в статус в определенный день - PullRequest
1 голос
/ 11 апреля 2019

Я пытаюсь преобразовать таблицу журнала изменений в таблицу исторического состояния с помощью стандартного SQL BigQuery.

Часть, которая заставляет меня повесить трубку, состоит в том, как выбрать самый последний журнал изменений, предшествующий датеприсоединяйтесь.

Я не сталкивался с оконными функциями или индексацией в течение моих студенческих лет, поэтому я был бы признателен за рекомендации о том, как применять эти функции, если они являются частью идеального решения.

Change_Logsтаблица

   Update                   Key      Tostring
1  2019-01-30 17:57:51.910  PS-5864  To Do
2  2019-02-11 20:59:08.582  PS-5864  In Progress
3  2019-02-12 19:52:18.733  PS-5864  Done
4  2019-01-31 16:52:12.832  PS-4672  To Do
5  2019-02-11 14:11:13.442  PS-4672  In Progress
6  2019-02-12 04:22:33.111  PS-4672  Done

таблица дат

   Date
1  2019-02-10
2  2019-02-11
3  2019-02-12
4  2019-02-13

желаемый результат:

   Date                     Key      Status
1  2019-02-10 00:00:00.000  PS-5864  To Do
2  2019-02-10 00:00:00.000  PS-4672  To Do
3  2019-02-11 00:00:00.000  PS-5864  To Do
4  2019-02-11 00:00:00.000  PS-4672  To Do
5  2019-02-12 00:00:00.000  PS-5864  In Progress
6  2019-02-12 00:00:00.000  PS-4672  In Progress
7  2019-02-13 00:00:00.000  PS-5864  Done
8  2019-02-13 00:00:00.000  PS-4672  Done

Ответы [ 2 ]

1 голос
/ 11 апреля 2019

Ниже для BigQuery Standard SQL

#standardSQL
SELECT d.date, key, 
  ARRAY_AGG(status ORDER BY l.update DESC LIMIT 1)[OFFSET(0)] status
FROM `project.dataset.dates` d
JOIN `project.dataset.change_logs` l
ON DATE_DIFF(d.date, DATE(l.update), DAY) > 0
GROUP BY d.date, key

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

#standardSQL
WITH `project.dataset.change_logs` AS (
  SELECT DATETIME '2019-01-30 17:57:51.910' `update`, 'PS-5864' key, 'To Do' status UNION ALL
  SELECT '2019-02-11 20:59:08.582', 'PS-5864', 'In Progress' UNION ALL
  SELECT '2019-02-12 19:52:18.733', 'PS-5864', 'Done' UNION ALL
  SELECT '2019-01-31 16:52:12.832', 'PS-4672', 'To Do' UNION ALL
  SELECT '2019-02-11 14:11:13.442', 'PS-4672', 'In Progress' UNION ALL
  SELECT '2019-02-12 04:22:33.111', 'PS-4672', 'Done' 
), `project.dataset.dates` AS (
  SELECT DATE '2019-02-10' `date` UNION ALL
  SELECT '2019-02-11' UNION ALL
  SELECT '2019-02-12' UNION ALL
  SELECT '2019-02-13' 
)
SELECT d.date, key, 
  ARRAY_AGG(status ORDER BY l.update DESC LIMIT 1)[OFFSET(0)] status
FROM `project.dataset.dates` d
JOIN `project.dataset.change_logs` l
ON DATE_DIFF(d.date, DATE(l.update), DAY) > 0
GROUP BY d.date, key
-- ORDER BY d.date, key   

с результатом

Row date        key     status   
1   2019-02-10  PS-4672 To Do    
2   2019-02-10  PS-5864 To Do    
3   2019-02-11  PS-4672 To Do    
4   2019-02-11  PS-5864 To Do    
5   2019-02-12  PS-4672 In Progress  
6   2019-02-12  PS-5864 In Progress  
7   2019-02-13  PS-4672 Done     
8   2019-02-13  PS-5864 Done    
0 голосов
/ 11 апреля 2019

Ключевой идеей является генерация строк с cross join.Тогда вы действительно хотите lag(. . . ignore nulls) - но не поддерживается в BigQuery.

Вместо этого вы можете выполнить некоторые манипуляции с массивами:

select d.date, cl.key,
       array_agg(cl.status ignore nulls order by d.date desc limit 2)[ordinal(2)]
from dates d cross join
     (select distinct key from change_logs cl) k left join
     change_logs cl
     on date(cl.update) = d.date and cl.key = k.key;

РЕДАКТИРОВАТЬ:

Выше не совсем правильно, потому что мы пропускаем даты, которые происходят до указанного периода.Я думаю, что самый простой способ - добавить их, а затем удалить их:

select *
from (select d.date, cl.key,
             array_agg(cl.status ignore nulls order by d.date desc limit 2)[ordinal(2)]
      from (select d.date
            from dates d 
            union 
            select distinct date(cl.update)
            from change_logs
           ) d cross join
           (select distinct key from change_logs cl) k left join
           change_logs cl
           on date(cl.update) = d.date and cl.key = k.key
    )
where date in (select d.date from dates);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...