在BigQuery

时间:2016-08-25 06:28:38

标签: sql google-bigquery

我在BigQuery中有一个表,其中包含ID字段和重复记录字段以及其他一些字段,如数据收集时间。

此表中有多个行用于每个ID,我想以某种方式为每个ID选择/合并一行。几乎每个解决方案,如选择最后一个,首先选择并在一行中聚合具有重复ID的行,在我的用例中是可以接受的,但到目前为止我无法使它们中的任何一个工作。

更确切地说,我的表有一个ID字段,在BigQuery术语中是: {name: ID, type: STRING, mode: NULLABLE}和重复的字段:{name: data, type: RECORD, mode: REPEATED}以及其他一些(普通)字段。 在我的表中,每个ID都有多行,每个ID都有一个重复的字段data。在我的查询结果中,我想要一个具有完全相同模式的表,其中每个ID只出现一次,并且其对应的data字段是data字段,来自原始表中出现的ID之一。 (或理想地从其所有出现中结合起来)

以下是无法解决的解决方案列表:

首先:使用

row_number() OVER (PARTITION BY ID ORDER BY collection_time) as rn ... where  rn=1

原因:即使使用了“Unflatten Results”选项,BigQuery也会在使用partition by时展平结果。

第二:选择具有最大/最小收集时间值的行:

因为:由于系统的其他部分存在一些重复,列的值对于我的表中的每个id都不是唯一的。

第三次:在其他字段中使用group by ID与nest / first

原因:在重复记录上使用nest会破坏记录字段中的关系。例如:SELECT ID, nest(data.a), nest(data.b)来自:

ID     data.a      data.b
--------------------------
1      1a1          null
       1a2          1b2
--------------------------
1      2a1          2b1
       null         2b2

结果

ID      data.a       data.b
----------------------------
1        1a1         1b2
         1a2         2b1
         2a1         2b2

2 个答案:

答案 0 :(得分:1)

您可以更轻松地使用standard SQL解决此问题(取消选中"使用旧版SQL"在"显示选项"下)。您可以将GROUP BYARRAY_CONCAT_AGG一起使用,例如:

SELECT id, ARRAY_CONCAT_AGG(data) AS data
FROM MyTable
GROUP BY id;

答案 1 :(得分:1)

在标准SQL模式下尝试以下

SELECT id, ARRAY_AGG(STRUCT(a, b)) AS data
FROM (
  SELECT id, a, ROW_NUMBER() OVER() AS num 
  FROM YourTable, UNNEST(data) WHERE NOT a IS NULL 
) FULL OUTER JOIN (
  SELECT id, b, ROW_NUMBER() OVER() AS num 
  FROM YourTable, UNNEST(data) WHERE NOT b IS NULL 
)  
USING(id, num) 
GROUP BY id  

它会在您的问题中提供您期望的exactly结果(消除NULL):

ID      data.a       data.b
----------------------------
1        1a1         1b2
         1a2         2b1
         2a1         2b2

如果(另一方面)你想保留原始的a / b对 - 你应该在下面使用(仍然在标准SQL模式下)

SELECT id, ARRAY_CONCAT_AGG(data) AS data
FROM YourTable
GROUP BY id

这为您提供了以下结果

ID      data.a       data.b
----------------------------
1        1a1         null
         1a2         1b2
         2a1         2b1
         null        2b2

您可以针对实际表格运行查询(将YourTable更改为实际表格 - >`project.dataset.table`),或者通过在代码前面添加相应查询并按原样运行来测试这两个查询

WITH YourTable AS (
  SELECT 1 AS id, ARRAY<STRUCT<a STRING, b STRING>>[('1a1', NULL),('1a2','1b2')] AS data UNION ALL
  SELECT 1 AS id, ARRAY<STRUCT<a STRING, b STRING>>[('2a1', '2b1'),(NULL,'2b2')] AS data 
)