BigQuery GROUP_CONCAT 和 ORDER BY

fso*_*ety 6 sql google-bigquery

我目前正在使用 BigQuery 和 GROUP_CONCAT,它们运行良好。但是,当我像在 SQL 中那样尝试将 ORDER BY 子句添加到 GROUP_CONCAT 语句时,我收到错误消息。

所以例如,像

SELECT a, GROUP_CONCAT(b ORDER BY c) FROM test GROUP BY a

如果我尝试指定分隔符,也会发生同样的情况。

关于如何解决这个问题的任何想法?

Mos*_*sky 10

BigQuery 中的标准 SQL 模式确实支持某些聚合函数中的 ORDER BY 子句,包括 STRING_AGG,例如:

#standardSQL
select string_agg(t.x order by t.y) 
from unnest([struct<x STRING, y INT64>('a', 5), ('b', 1), ('c', 10)]) t
Run Code Online (Sandbox Code Playgroud)

会导致

b,a,c

文档在这里:https : //cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#using-order-by-with-aggregate-functions


Mos*_*sky 5

由于 BigQuery 不支持 GROUP_CONCAT 函数内的 ORDER BY 子句,因此可以通过使用解析窗口函数来实现此功能。在 BigQuery 中,GROUP_CONCAT 的分隔符只是该函数的第二个参数。下面的例子说明了这一点:

select key, first(grouped_value) concat_value from (
select 
  key, 
  group_concat(value, ':') over 
    (partition by key
     order by value asc
     rows between unbounded preceding and unbounded following) 
  grouped_value 
from (
select key, value from
(select 1 as key, 'b' as value),
(select 1 as key, 'c' as value),
(select 1 as key, 'a' as value),
(select 2 as key, 'y' as value),
(select 2 as key, 'x' as value))) group by key
Run Code Online (Sandbox Code Playgroud)

将产生以下内容:

Row key concat_value     
1   1   a:b:c    
2   2   x:y
Run Code Online (Sandbox Code Playgroud)

关于窗口规范的注意事项:查询使用“无界前面和无界后面之间的行”窗口规范,以确保分区内的所有行都参与 GROUP_CONCAT 聚合。每个 SQL 标准默认窗口规范是“无界前一行和当前行之间的行”,这对运行总和之类的事情有好处,但在此问题中无法正常工作。

性能说明:尽管多次重新计算聚合函数看起来很浪费,但 BigQuery 优化器确实认识到,由于窗口没有改变,结果将是相同的,因此它每个分区只计算一次聚合。