You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL中如何对数组字段执行逐元素Avg()聚合并保留维度

这个需求完全可以实现,核心逻辑是先把数组拆分为元素和对应下标的行数据,按下标分组计算平均值后,再按下标顺序重组为数组,就能保留原数组的维度和顺序。

方法1:直接查询(无需额外定义函数)

直接写SQL查询即可实现,适合临时查询场景:

SELECT array_agg(elem_avg ORDER BY idx) AS x
FROM (
    SELECT
        idx,
        AVG(elem) AS elem_avg
    FROM
        my_arrays,
        unnest(array_field) WITH ORDINALITY AS arr(elem, idx)
    GROUP BY idx
) t;

逻辑说明:unnest函数加WITH ORDINALITY参数会把数组的每个元素和它的对应下标(从1开始)拆分为独立行,按下标分组求平均值后,再用array_agg按下标顺序把平均值聚合为数组。

方法2:自定义聚合函数(可直接调用)

如果你需要像使用内置avg函数一样直接调用,可以提前自定义一个数组逐元素求平均的聚合函数:

-- 定义数组逐元素求和的过渡函数
CREATE OR REPLACE FUNCTION array_sum_step(state float[], elem float[])
RETURNS float[] AS $$
SELECT array_agg(coalesce(s, 0) + coalesce(e, 0) ORDER BY idx)
FROM unnest(state) WITH ORDINALITY a(s, idx)
FULL OUTER JOIN unnest(elem) WITH ORDINALITY b(e, idx) USING (idx);
$$ LANGUAGE sql IMMUTABLE;

-- 定义最终计算平均值的收尾函数
CREATE OR REPLACE FUNCTION array_avg_final(state float[], count integer)
RETURNS float[] AS $$
SELECT array_agg(elem / count ORDER BY idx)
FROM unnest(state) WITH ORDINALITY a(elem, idx);
$$ LANGUAGE sql IMMUTABLE;

-- 注册自定义聚合函数
CREATE AGGREGATE avg_arr(float[]) (
    SFUNC = array_sum_step,
    STYPE = float[],
    FINALFUNC = array_avg_final,
    FINALFUNC_EXTRA = true,
    INITCOND = '{}'
);

定义完成后就可以用和你期望非常接近的语法查询:

SELECT avg_arr(array_field) AS x FROM my_arrays;

两种方法基于你提供的测试数据执行后,都会返回你预期的结果:

x
---------
{2, 2, 2}

注意:以上实现默认所有行的数组长度相同,如果存在数组长度不一致的情况,可根据业务需求调整缺省值处理逻辑。

内容的提问来源于stack exchange,提问作者Clebo Sevic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 19:15:03