Свертывание SQL ежедневной таблицы состояния в SCD - PullRequest
1 голос
/ 24 января 2020

У меня есть таблица с ежедневным статусом, которую я хотел бы свернуть в SCD.

+----+------------+--------+
| id | cal_date   | status |
+----+------------+--------+
| 1  | 2020-01-01 | A      |
+----+------------+--------+
| 1  | 2020-01-02 | B      |
+----+------------+--------+
| 1  | 2020-01-03 | B      |
+----+------------+--------+
| 1  | 2020-01-04 | B      |
+----+------------+--------+
| 1  | 2020-01-05 | C      |
+----+------------+--------+
| 1  | 2020-01-06 | C      |
+----+------------+--------+
| 1  | 2020-01-07 | B      |
+----+------------+--------+
| 1  | 2020-01-08 | B      |
+----+------------+--------+
| 1  | 2020-01-09 | C      |
+----+------------+--------+
| 1  | 2020-01-10 | C      |
+----+------------+--------+
| 1  | 2020-01-11 | B      |
+----+------------+--------+
| 1  | etc        | B      |
+----+------------+--------+
| 1  | 2020-01-23 | B      |
+----+------------+--------+

сворачивается в

+----+--------+----------------------+---------------------------------------+
| id | status | effective_start_date | effective_end_date                    |
+----+--------+----------------------+---------------------------------------+
| 1  | A      | 2020-01-01           | 2020-01-01                            |
+----+--------+----------------------+---------------------------------------+
| 1  | B      | 2020-01-02           | 2020-01-04                            |
+----+--------+----------------------+---------------------------------------+
| 1  | C      | 2020-01-05           | 2020-01-06                            |
+----+--------+----------------------+---------------------------------------+
| 1  | B      | 2020-01-07           | 2020-01-08                            |
+----+--------+----------------------+---------------------------------------+
| 1  | C      | 2020-01-09           | 2020-01-10                            |
+----+--------+----------------------+---------------------------------------+
| 1  | B      | 2020-01-11           | NULL (or 2020-01-23 or 2099-12-31)    |
+----+--------+----------------------+---------------------------------------+

Я думаю, что это было бы довольно просто, если бы статусы были порядковыми / направленными (только A-> B -> C), но этот шаблон (A-> B -> C -> B -> C -> B), где любой статус может повторяться, является броском меня выключить Если не будет никаких изменений в статусе, этот пользователь будет получать запись статуса B за каждый день на неопределенный срок. Есть ли удобный способ сделать это в BigQuery?

with data as (
  select 1 as id, cast('2020-01-01' as date) as cal_date, 'A' as status UNION ALL
  select 1, '2020-01-02','B' UNION ALL  select 1, '2020-01-03','B' UNION ALL  select 1, '2020-01-04','B' UNION ALL
  select 1, '2020-01-05','C' UNION ALL  select 1, '2020-01-06','C' UNION ALL  select 1, '2020-01-07','B' UNION ALL
  select 1, '2020-01-08','B' UNION ALL  select 1, '2020-01-09','C' UNION ALL  select 1, '2020-01-10','C' UNION ALL
  select 1, '2020-01-11','B' UNION ALL  select 1, '2020-01-12','B' UNION ALL  select 1, '2020-01-13','B' UNION ALL
  select 1, '2020-01-14','B' UNION ALL  select 1, '2020-01-15','B' UNION ALL  select 1, '2020-01-16','B' UNION ALL
  select 1, '2020-01-17','B' UNION ALL  select 1, '2020-01-18','B' UNION ALL  select 1, '2020-01-19','B' UNION ALL
  select 1, '2020-01-20','B' UNION ALL  select 1, '2020-01-21','B' UNION ALL  select 1, '2020-01-22','B' UNION ALL
  select 1, '2020-01-23','B' 
 )
 select * from data 

1 Ответ

3 голосов
/ 24 января 2020

Ниже для BigQuery Standard SQL

#standardSQL
SELECT id, status, 
  MIN(cal_day) effective_start_date, 
  MAX(cal_day) effective_end_date
FROM (
  SELECT *, COUNTIF(new_group) OVER(PARTITION BY id ORDER BY cal_day) group_number
  FROM (
    SELECT *, status != LAG(status, 1, '') OVER(PARTITION BY id ORDER BY cal_day) new_group
    FROM `project.dataset.data`
  )
)
GROUP BY id, status, group_number 
-- ORDER BY id, effective_start_date   

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

Row id  status  effective_start_date    effective_end_date   
1   1   A       2020-01-01              2020-01-01   
2   1   B       2020-01-02              2020-01-04   
3   1   C       2020-01-05              2020-01-06   
4   1   B       2020-01-07              2020-01-08   
5   1   C       2020-01-09              2020-01-10   
6   1   B       2020-01-11              2020-01-23   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...