BigQuery:如何在重复记录中插入新值?

Posted

技术标签:

【中文标题】BigQuery:如何在重复记录中插入新值?【英文标题】:BigQuery: How to insert a new value in repeated record? 【发布时间】:2018-11-05 11:00:53 【问题描述】:

我想保存用户状态的历史记录。

为此,我有一个包含两个列的表:user_identifier 和 status。

user_identifier 是一个字符串,status 是一个重复的记录,键:值对:日期和状态。

当用户更改状态(例如从活动状态变为非活动状态)时,我想更新此表并添加新状态,同时保留旧状态。

这是表架构:

[

"description": "user identifier",
"mode": "REQUIRED",
"name": "user_id",
"type": "STRING"
,

"description": "status - can be either sent or pending, initial state is pending",
"mode": "REPEATED",
"name": "status",
"type": "RECORD",
"fields": [
  
  "name": "status_date",
  "type": "DATE",
  "mode": "REQUIRED"
  ,
  
  "name": "value",
  "type": "STRING",
  "mode": "REQUIRED"
  
]

]

这甚至可以在此架构中插入新的用户状态吗?我应该重新设计架构吗? 如何在 BigQuery 中正确执行此操作,以利用其嵌套功能?

【问题讨论】:

【参考方案1】:

以下是 BigQuery 标准 SQL,并假设您有一个状态表 project.dataset.statuses,如您在问题中所述,并且您有更新表 project.dataset.updates,您可以在其中累积更新以定期更新状态表

所以虚拟数据可能看起来像

WITH `project.dataset.statuses` AS (
  SELECT 'a' user_id, [STRUCT<status_date DATE, value STRING>('2018-11-03', 'pending')] status UNION ALL
  SELECT 'b', [STRUCT<status_date DATE, value STRING>('2018-11-04', 'pending')] UNION ALL
  SELECT 'c', [] 
), `project.dataset.updates` AS (
  SELECT 'a' user_id, [STRUCT<status_date DATE, value STRING>('2018-11-05', 'sent')] new_statuses UNION ALL
  SELECT 'c', [STRUCT<status_date DATE, value STRING>('2018-11-05', 'pending')]
)

其中更新表具有完全相同的架构并表示需要添加到主表的新更新

SELECT 下方返回加入状态

#standardSQL
SELECT 
  t.user_id, 
  IF(u.user_id IS NULL, status, ARRAY_CONCAT(status, new_statuses)) status
FROM `project.dataset.statuses` t
LEFT JOIN `project.dataset.updates` u
ON t.user_id = u.user_id   

您可以使用下面的 DDL 来“更新”它们的状态表

#standardSQL
CREATE OR REPLACE TABLE `project.dataset.statuses` AS
SELECT 
  t.user_id, 
  IF(u.user_id IS NULL, status, ARRAY_CONCAT(status, new_statuses)) status
FROM `project.dataset.statuses` t
LEFT JOIN `project.dataset.updates` u
ON t.user_id = u.user_id   

如果应用于虚拟数据

状态:

Row user_id status.status_date  status.value     
1   a       2018-11-03          pending  
2   b       2018-11-04          pending  
3   c             

更新:

Row user_id new_statuses.status_date    new_statuses.value   
1   a       2018-11-05          sent     
3   c       2018-11-05          pending  

结果将是

Row user_id status.status_date  status.value     
1   a       2018-11-03          pending  
            2018-11-05          sent     
2   b       2018-11-04          pending  
3   c       2018-11-05          pending    

如果updates 表可以包含尚未在主表中的新用户 - 下面将处理这种情况

#standardSQL
-- CREATE OR REPLACE TABLE `project.dataset.statuses` AS
SELECT 
  IFNULL(t.user_id, u.user_id) user_id,
  CASE 
    WHEN t.user_id = u.user_id THEN ARRAY_CONCAT(status, new_statuses)
    WHEN t.user_id IS NULL THEN new_statuses
    WHEN u.user_id IS NULL THEN status
  END status
FROM `project.dataset.statuses` t
FULL JOIN `project.dataset.updates` u
ON t.user_id = u.user_id   

【讨论】:

以上是关于BigQuery:如何在重复记录中插入新值?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 bigrquery 库将非重复记录插入 BigQuery?

bigquery重复记录中的数据顺序

SQL 防止重复插入

BigQuery:如何从重复记录中仅提取某些字段作为另一个重复字段

如何使用 SQL 将重复数据插入 BigQuery 表

Bigquery 分区表中的重复项