SQL使用GROUP BY时如何将所有列自动聚合为数组,是否支持array_agg(*)语法
给定参考数据表
| item | vietnamese | cost | unique_id |
|---|---|---|---|
| fruits | trai cay | 10 | abc123 |
| fruits | trai cay | 8 | foo99 |
| fruits | trai cay | 9 | foo99 |
| fruits | trai cay | 12 | abc123 |
| fruits | trai cay | 14 | abc123 |
| vege | rau | 3 | rr1239 |
| vege | rau | 3 | rr1239 |
问题解答:SQL是否支持
array_agg(*)自动聚合所有列 明确结论:标准SQL以及绝大多数主流关系型数据库(PostgreSQL、MySQL、SQL Server等)均不原生支持直接使用array_agg(*)的语法,来自动对所有非分组字段执行array_agg聚合。
如果需要跨数据库兼容,最稳妥的方式就是你示例中提到的逐个指定字段的聚合写法,兼容性最好,逻辑也最清晰。
可替代的简化实现方案
方案1:整行聚合(适用PostgreSQL、BigQuery等支持行类型的数据库)
如果不需要把每个字段单独拆成独立数组,可以直接将整行作为聚合单位,将所有字段打包到同一个数组的元素中,写法如下:
SELECT item, array_agg(mytable.*) AS aggregated_rows FROM mytable GROUP BY item
返回结果中aggregated_rows字段为行类型/结构体数组,可通过对应语法提取内部字段,例如PostgreSQL中可通过(aggregated_rows[1]).cost获取分组下第一行的cost值。
方案2:动态SQL生成聚合语句
如果需要每个字段单独生成聚合数组,不想手动逐个写列名,可以用动态SQL拼接查询语句,以PostgreSQL为例:
- 首先查询非分组字段的聚合语句片段:
SELECT string_agg(format('array_agg(%I) AS %I', column_name, column_name), ', ') FROM information_schema.columns WHERE table_name = 'mytable' AND column_name != 'item';
- 将上述查询返回的字符串,替换到正式查询的SELECT部分即可。
补充说明
SQL语法中仅count(*)对星号做了特殊处理(代表统计行数),其余聚合函数的入参都要求是明确的单个表达式,因此array_agg(*)不符合通用SQL的设计规范,不会被默认支持。
内容的提问来源于stack exchange,提问作者alvas
相关产品推荐
相关产品推荐

