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

PostgreSQL中如何高效计算去除高低分后的行平均分数?

PostgreSQL 简洁实现去高低分求平均

直接用数组函数结合聚合逻辑就能替代臃肿的UNION ALL写法,而且后续新增score列时只需要修改数组里的列名,非常灵活:

方案一:数组聚合计算法

把所有score列打包成数组,通过拆分行后直接计算总和减去最大最小值,再除以剩余的有效分数数量:

SELECT
    id,
    (SUM(s) - MAX(s) - MIN(s)) / (COUNT(s) - 2) AS avg_score
FROM scores, unnest(ARRAY[score1, score2, score3, score4, score5, score6, score7]) s
GROUP BY id;

这个写法利用unnest将数组拆分为行,再按ID分组计算,逻辑清晰,执行效率远高于UNION ALL的拆分方式。

方案二:窗口函数过滤极值

如果需要严格匹配“各去掉一个最高分和最低分”的逻辑(哪怕存在多个相同极值,也仅各剔除一个),可以用窗口函数标记行号后过滤:

SELECT
    id,
    AVG(score) AS avg_score
FROM (
    SELECT
        id,
        score,
        ROW_NUMBER() OVER (PARTITION BY id ORDER BY score) AS rn_low,
        ROW_NUMBER() OVER (PARTITION BY id ORDER BY score DESC) AS rn_high
    FROM scores, unnest(ARRAY[score1, score2, score3, score4, score5, score6, score7]) score
) t
WHERE rn_low > 1 AND rn_high > 1
GROUP BY id;

该方案完全贴合你给出的示例逻辑——比如ID3的全7分数据,会去掉一个最高和一个最低分后保留5个7,最终平均仍为7。

适配新增列

后续如果新增score8、score9等列,仅需在数组中补充对应的列名即可,比如ARRAY[score1, score2, ..., score9],无需修改整体查询结构,比UNION ALL的方式省心得多。

处理空值场景

如果score列可能存在NULL值,只需在过滤条件中添加空值判断:

WHERE score IS NOT NULL AND rn_low > 1 AND rn_high > 1

内容的提问来源于stack exchange,提问作者heihei Li

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 06:44:55