array_agg需用括号内ORDER BY保证结果有序,如array_agg(col ORDER BY col);去重须先unnest再distinct最后array_agg;string_agg去重需在子查询中完成,且NULL分隔符会导致整个结果为NULL。
array_agg 怎么保证结果有序
array_agg 默认不保序,即使输入数据已排序,聚合后顺序仍可能错乱。必须显式用 ORDER BY 子句控制内部排序,写法是:array_agg(col ORDER BY col) 或 array_agg(col ORDER BY col DESC)。注意这个 ORDER BY 是写在括号里、紧贴函数名后的,不是外面的 ORDER BY;否则只影响最终查询结果排序,不影响数组元素顺序。
常见错误是写成:SELECT array_agg(col) FROM t ORDER BY col——这只会让整行结果按 col 排,array_agg 里元素仍是随机顺序。
- 多字段排序也支持:
array_agg(name ORDER BY dept, salary DESC) - 若排序字段含 NULL,默认排在最前;加
NULLS LAST可调整:array_agg(x ORDER BY x NULLS LAST) - 子查询中嵌套使用时,
ORDER BY仍需放在函数括号内,不能移到外层
string_agg 去重必须先 distinct 再聚合
string_agg 本身不提供去重参数,也不能在函数内部写 DISTINCT(会报错 syntax error at or near "DISTINCT")。正确做法是把去重逻辑上推到输入源:用子查询或 CTE 先 DISTINCT,再喂给 string_agg。
例如想拼接去重后的标签列表:SELECT string_agg(tag, ', ') FROM (SELECT DISTINCT tag FROM tags WHERE post_id = 123) t。如果还要求有序,就在子查询里加 ORDER BY:(SELECT DISTINCT tag FROM tags WHERE post_id = 123 ORDER BY tag)。
- 别试图用
string_agg(DISTINCT tag, ', ')——语法不合法 - 用
GROUP BY配合DISTINCT时要注意:若分组键和去重字段不同,DISTINCT作用范围是整个 SELECT 列表,容易误去重 - 性能敏感场景下,
DISTINCT+string_agg比用窗口函数或递归 CTE 更轻量,优先选前者
array_agg 去重只能靠 unnest + distinct + array_agg 组合
array_agg 同样不支持内置去重,但比 string_agg 多一层转换成本:得先把数组展开、去重、再聚合成新数组。典型写法:(SELECT ARRAY(SELECT DISTINCT UNNEST(array_agg(col)) ORDER BY 1))。