BigQuery 从查询中创建重复记录字段

Posted

技术标签:

【中文标题】BigQuery 从查询中创建重复记录字段【英文标题】:BigQuery creat repeated record field from query 【发布时间】:2016-01-11 21:54:29 【问题描述】:

是否可以在 BigQuery 中创建重复记录列?例如,对于以下数据:

| a | b | c |
-------------
| 1 | 5 | 2 |
-------------
| 1 | 3 | 1 |
-------------
| 2 | 2 | 1 |

以下可能吗?

Select a, NEST(b, c) as d from *table* group by a

产生以下结果

| a | d.b | d.c |
-----------------
| 1 |  5  |  2  |
-----------------
|   |  3  |  1  |
-----------------
| 2 |  2  |  1  |

【问题讨论】:

【参考方案1】:

随着 BigQuery 标准 SQL 的引入,我们有了处理记录的简单方法 试试下面,不要忘记取消选中 Show Options 下的 Use Legacy SQL 复选框

WITH YourTable AS (
  SELECT 1 AS a, 5 AS b, 2 AS c UNION ALL
  SELECT 1 AS a, 3 AS b, 1 AS c UNION ALL
  SELECT 2 AS a, 2 AS b, 1 AS c
)
SELECT a, ARRAY_AGG(STRUCT(b, c)) AS d
FROM YourTable 
GROUP BY a

【讨论】:

【参考方案2】:

绕过NEST()“嵌套”一个字段的限制的一种方法是使用BigQuery User-Defined Functions。它们非常强大,但仍有一些 Limits 和 Limitations 需要注意。最重要的是,我的未来要记住 - 他们非常有资格获得昂贵的High-Compute queries

复杂的查询会消耗非常大的计算资源 相对于处理的字节数。通常,此类查询 包含非常大量的 JOIN 或 CROSS JOIN 子句或复杂的 用户自定义函数。

因此,下面是从 questino 示例中“模仿”NEST(b, c) 的示例:

SELECT a, d.b, d.c FROM 
JS((      // input table
  SELECT a, NEST(CONCAT(STRING(b), ',', STRING(c))) AS d
  FROM (
    SELECT * FROM 
    (SELECT 1 AS a, 5 AS b, 2 AS c),
    (SELECT 1 AS a, 3 AS b, 1 AS c),
    (SELECT 2 AS a, 2 AS b, 1 AS c)
  ) GROUP BY a),
  a, d,     // input columns
  "['name': 'a', 'type': 'INTEGER',    // output schema
    'name': 'd', 'type': 'RECORD',
     'mode': 'REPEATED',
     'fields': [
       'name': 'b', 'type': 'STRING',
       'name': 'c', 'type': 'STRING'
     ]    
    
  ]",
  "function(row, emit)    // function 
    var c = [];
    for (var i = 0; i < row.d.length; i++) 
      x = row.d[i].toString().split(',');
      t = b:x[0], c:x[1]
      c.push(t);
    ;
    emit(a: row.a, d: c);  
  "
)

它相对简单。我希望你能够通过它并得到一个想法

仍然-记住:

无论您如何使用嵌套/重复字段创建记录 - BigQuery 自动展平查询结果,因此可见结果不会包含 重复的字段。因此,您应该将其用作产生的子选择 供同一查询立即使用的中间结果。

作为仅供参考,您可以通过运行以下查询来证明上述仅返回两条记录(而不是展平时的三条记录)

SELECT COUNT(1) AS rows FROM (
  <above query here>
) 

另一个重要的注意事项: 这是众所周知的NEST()UnFlatten Results 输出不兼容,主要用于子查询中的中间结果。 相比之下,上述解决方案可以很容易地直接保存到表中(未选中 Flatten Results)

【讨论】:

【参考方案3】:

BigQuery 会自动展平查询结果,因此如果您使用 NEST ***查询的函数,结果不会包含重复 字段。使用产生的子选择时使用 NEST 函数 供同一查询立即使用的中间结果。

在https://cloud.google.com/bigquery/query-reference#aggfunctions查看更多关于 NEST() 的信息

还要检查 Big Query - Group By Clause not working with NEST() 以供参考

要记住的另一点 - 你只能嵌套一个字段 - NEST(b) 但不能 NEST(b, c)

也就是说 - 你可以产生类似于你所要求的结果,但你需要把它写到表中

根据我的经验:用户在将数据加载到 BigQuery 时会更多地面临这个问题——也就是说,用户可以根据需要使用具有复杂架构的 nlJSON。 GBQ本身的用户通常对分析、聚合比较感兴趣,所以上述类型的问题出现的频率较低。我认为当前的 GBQ sysntax 不够友好/灵活,无法生成“复杂”分层/嵌套模式的数据并将其插入到仅在 GBQ 中的表中。不过,我认为解决方法是可能的,但取决于具体的用例

【讨论】:

嵌套多个字段是我真正要问的。 我认为,很遗憾,NEST(b) 现在不支持。会很好!您可以提交您的提案

以上是关于BigQuery 从查询中创建重复记录字段的主要内容,如果未能解决你的问题,请参考以下文章

重复字段的 BigQuery 记录

BigQuery 重复数据删除和分区表

bigquery 嵌套和重复字段查询

将 BigQuery 查询结果行写入 csv 文件时,某些记录重复

BigQuery - 删除重复记录有时需要很长时间

BigQuery:选择重复记录中字段之间的最小差异