使用附加模型在BigQuery中进行部分行更新

时间:2019-04-12 01:36:26

标签: sql google-cloud-platform google-bigquery

假设我在BQ中有以下记录:

id        name           age    timestamp
1         "tom"          20     2019-01-01

然后,我使用流API来“附加”附加数据-https://cloud.google.com/bigquery/streaming-data-into-bigquery,对此记录执行两次“更新”。这主要是为了避免BQ强制执行的更新配额(这是我们拥有的高性能应用程序)。

然后,我将两个编辑附加到表中,一个更新仅修改name,然后一个更新仅修改age。这是更新后的三个记录:

id        name           age    timestamp
1         "tom"          20     2019-01-01
1         "Tom"          null   2019-02-01
1         null           21     2019-03-03

然后,我想查询该记录以获取最新的信息。这是我的开始方式:

SELECT id, **name**, **age**,max(timestamp)
FROM table
GROUP BY id 
-- 1,"Tom",21,2019-03-03

在这里如何获得正确的姓名和年龄?请注意,一条记录可能有成千上万的更新,因此,如果可能的话,我不想编写1000个case语句。

由于各种其他原因,我通常一次不会拥有所有行数据,而只会拥有RowID + FieldName + FieldValue。

我想这里的计划B是执行查询以获取当前数据,然后添加我的更改以插入新行,但是我希望有一种方法可以一次性执行此操作而不必执行两次查询。

2 个答案:

答案 0 :(得分:4)

以下是用于BigQuery标准SQL

#standardSQL
SELECT id, 
  ARRAY_AGG(name IGNORE NULLS ORDER BY ts DESC LIMIT 1)[OFFSET(0)] name,
  ARRAY_AGG(age IGNORE NULLS ORDER BY ts DESC LIMIT 1)[OFFSET(0)] age,
  MAX(ts) ts  
FROM `project.dataset.table`
GROUP BY id   

您可以使用问题中的示例数据来进行测试,如上示例所示

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 id, "tom" name, 20 age, DATE '2019-01-01' ts UNION ALL
  SELECT 1, "Tom", NULL, '2019-02-01' UNION ALL
  SELECT 1, NULL, 21, '2019-03-03' 
)
SELECT id, 
  ARRAY_AGG(name IGNORE NULLS ORDER BY ts DESC LIMIT 1)[OFFSET(0)] name,
  ARRAY_AGG(age IGNORE NULLS ORDER BY ts DESC LIMIT 1)[OFFSET(0)] age,
  MAX(ts) ts  
FROM `project.dataset.table`
GROUP BY id   

有结果

Row id  name    age ts   
1   1   Tom 21  2019-03-03  

答案 1 :(得分:0)

这是在标准SQL中应用解析函数的经典案例。

这是您达到目标的方法:

select id, name, age from (
  select id, name, age, ts, rank() over (partition by id order by ts desc) rnk
  from `yourdataset.yourtable`
)
where rnk = 1

这将基于id将您的记录分组,并选择最近的ts的记录(表示为给定id添加的最近记录)。