PostgreSQL数组如何移除连续重复值并保留非连续重复项
现有方案合理性评估
你的实现逻辑完全正确,是PostgreSQL处理数组连续去重的标准思路:通过拆解数组保留原始顺序、对比相邻元素过滤重复值、再重新聚合,完全符合保留非连续重复值、不改变原有顺序的需求,没有逻辑漏洞。
简化优化方案
原写法确实可以大幅精简,核心是用unnest() WITH ORDINALITY直接获取数组元素的原始序号,不需要额外生成行号,减少CTE层级,优化后写法如下:
SELECT array_agg(val ORDER BY ord) AS array_logical FROM ( SELECT val, ord, LAG(val) OVER (ORDER BY ord) AS prev_val FROM unnest(ARRAY['A', 'B', 'C', 'C', 'D', 'A']) WITH ORDINALITY AS t(val, ord) ) t WHERE prev_val IS DISTINCT FROM val;
该写法和你原逻辑完全等价,执行效率更高,代码也更简洁。
封装建议
- 如果该逻辑需要在多处查询中复用,强烈建议封装为immutable类型的SQL函数,调用更便捷,也能获得更好的查询优化效果,函数示例:
CREATE OR REPLACE FUNCTION array_remove_consecutive_duplicates(anyarray) RETURNS anyarray LANGUAGE sql IMMUTABLE AS $$ SELECT array_agg(val ORDER BY ord) FROM ( SELECT val, ord, LAG(val) OVER (ORDER BY ord) AS prev_val FROM unnest($1) WITH ORDINALITY AS t(val, ord) ) t WHERE prev_val IS DISTINCT FROM val; $$;
调用方法非常简单:
SELECT array_remove_consecutive_duplicates(ARRAY['A', 'B', 'C', 'C', 'D', 'A']);
直接返回结果{A,B,C,D,A}。
- 如果只是单次场景使用,直接把简化后的查询嵌入业务语句即可,不需要额外封装。
内容的提问来源于stack exchange,提问作者GeoGyro
相关产品推荐
相关产品推荐

