BigQuery GROUP_CONCAT 和 ORDER BY
BigQuery GROUP_CONCAT and ORDER BY
我目前正在使用 BigQuery 和 GROUP_CONCAT,它工作得很好。但是,当我尝试像在 SQL 中那样向 GROUP_CONCAT 语句添加 ORDER BY 子句时,我收到错误消息。
例如,
SELECT a, GROUP_CONCAT(b ORDER BY c)
FROM test
GROUP BY a
如果我尝试指定分隔符,也会发生同样的情况。
关于如何处理这个问题有什么想法吗?
由于 BigQuery 不支持 GROUP_CONCAT 函数内的 ORDER BY 子句,因此可以通过使用解析 window 函数来实现此功能。在 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
将产生以下内容:
Row key concat_value
1 1 a:b:c
2 2 x:y
关于 Window 规范的注意事项:查询使用 "rows between unbounded preceding and unbounded following" window 规范,以确保分区中的所有行都参与 GROUP_CONCAT 聚合。根据 SQL 标准默认 window 规范是 "rows between unbounded preceding and current row" 这对于 运行 总和之类的东西很有用,但在这个问题中不能正常工作。
性能说明:尽管多次重新计算聚合函数看起来很浪费,但 BigQuery 优化器确实认识到,由于 window 没有改变结果将是相同的,因此它只为每个分区计算一次聚合。
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
将导致
b,a,c
这是 BigQuery 中标准 SQL 模式的一个版本,其中 ARRAY_AGG 作为聚合函数:
select key,
array_agg(struct(grouped_value) order by array_length(grouped_value) desc limit 1)[offset(0)].*
from (
select
key,
array_agg(value) over
(partition by key
order by value asc
rows between unbounded preceding and unbounded following)
grouped_value
from (
select key, value from unnest([
struct(1 as key, "b" as value)
, struct(1, "c")
, struct(1, "a")
, struct(2, "y")
, struct(2, "x")
]))) group by key
我目前正在使用 BigQuery 和 GROUP_CONCAT,它工作得很好。但是,当我尝试像在 SQL 中那样向 GROUP_CONCAT 语句添加 ORDER BY 子句时,我收到错误消息。
例如,
SELECT a, GROUP_CONCAT(b ORDER BY c)
FROM test
GROUP BY a
如果我尝试指定分隔符,也会发生同样的情况。
关于如何处理这个问题有什么想法吗?
由于 BigQuery 不支持 GROUP_CONCAT 函数内的 ORDER BY 子句,因此可以通过使用解析 window 函数来实现此功能。在 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
将产生以下内容:
Row key concat_value
1 1 a:b:c
2 2 x:y
关于 Window 规范的注意事项:查询使用 "rows between unbounded preceding and unbounded following" window 规范,以确保分区中的所有行都参与 GROUP_CONCAT 聚合。根据 SQL 标准默认 window 规范是 "rows between unbounded preceding and current row" 这对于 运行 总和之类的东西很有用,但在这个问题中不能正常工作。
性能说明:尽管多次重新计算聚合函数看起来很浪费,但 BigQuery 优化器确实认识到,由于 window 没有改变结果将是相同的,因此它只为每个分区计算一次聚合。
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
将导致
b,a,c
这是 BigQuery 中标准 SQL 模式的一个版本,其中 ARRAY_AGG 作为聚合函数:
select key,
array_agg(struct(grouped_value) order by array_length(grouped_value) desc limit 1)[offset(0)].*
from (
select
key,
array_agg(value) over
(partition by key
order by value asc
rows between unbounded preceding and unbounded following)
grouped_value
from (
select key, value from unnest([
struct(1 as key, "b" as value)
, struct(1, "c")
, struct(1, "a")
, struct(2, "y")
, struct(2, "x")
]))) group by key