PostgreSQL中多次调用聚合函数的行顺序是否能保持一致?
问题结论
首先明确:你观察到的多个array_agg行处理顺序一致的现象不是PostgreSQL官方保证的可依赖特性,仅为当前版本实现的偶然行为,生产环境禁止直接依赖该特性,否则后续版本升级、查询计划变化、并行扫描开启等场景都可能出现键值错位的问题。
官方规则说明
PostgreSQL文档明确规定:不带ORDER BY子句的聚合函数,处理分组内的行的顺序是未定义的。当前版本的实现中,同一分组下的多个无排序聚合确实会复用同一次扫描的行顺序,但该行为不属于兼容性承诺范围,没有任何官方保障会长期维持。
可靠实现方案
方案1:为每个array_agg指定相同排序规则
给所有array_agg加上完全一致的ORDER BY子句,官方保证排序规则相同的前提下,生成的数组下标会严格对应:
select g, json_object(array_agg(cast (a as text) ORDER BY a), array_agg(b ORDER BY a)) from test group by g
你可以任意选择排序维度(比如按a、按b、甚至按隐藏字段ctid都可以),只要两个array_agg的排序规则完全一致即可。
方案2:直接使用json_object_agg聚合(推荐)
PostgreSQL 9.4及以上版本支持json_object_agg聚合函数,可以直接聚合生成json对象,不需要先拆分两个数组,写法更简洁,天然保证键值对应:
select g, json_object_agg(cast(a as text), b ORDER BY a) from test group by g
该方案性能更优,也避免了多个聚合排序规则不一致的人为失误,是最优实现。
内容的提问来源于stack exchange,提问作者sifear
相关产品推荐
相关产品推荐

