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

PostgreSQL中如何基于累积和对连续数字动态分组(组和不超阈值)

PostgreSQL 实现连续数字按动态和阈值分组

需求

  • 输入范围:1到max_num(示例为100)的连续整数,max_num与组和阈值sum_threshold(示例为20)为动态参数,禁止硬编码
  • 分组规则:
    • 尽可能将连续数字归为一组,组内数字之和不得超过阈值
    • 若单个数字本身超过阈值,则单独成组
  • 示例输出(阈值20,max_num=100):
    • 第1组:1,2,3,4,5 → 和15(≤20)
    • 第2组:6,7 → 和13(≤20)
    • 第3组:8,9 → 和17(≤20)
    • 第4组:10 → 和10(≤20)
    • ...
    • 第n-1组:99 → 和99(>20,单独成组)
    • 第n组:100 → 和100(>20,单独成组)

解决方案

方法1:窗口函数实现

通过计算组内累积和与分组标识完成分组,适合大数据量场景:

WITH params AS (
    SELECT 
        100 AS max_num,  -- 可修改的最大值参数
        20 AS sum_threshold  -- 可修改的组和阈值参数
)
SELECT 
    array_agg(n ORDER BY n) AS group_numbers,
    sum(n) AS group_sum
FROM (
    SELECT 
        n,
        -- 生成分组ID:当前组累积和超过阈值时,分组编号递增
        SUM(CASE WHEN group_running_sum > (SELECT sum_threshold FROM params) THEN 1 ELSE 0 END) OVER (ORDER BY n) AS group_id
    FROM (
        SELECT 
            n,
            -- 计算当前组的累积和:减去之前已完成分组的总和,得到当前组累计值
            n + COALESCE(
                SUM(n) OVER (ORDER BY n ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) 
                - SUM(CASE WHEN global_running_sum > (SELECT sum_threshold FROM params) THEN global_running_sum ELSE 0 END) OVER (ORDER BY n),
                0
            ) AS group_running_sum
        FROM (
            SELECT 
                n,
                -- 计算全局累积和,用于判断是否需开启新分组
                SUM(n) OVER (ORDER BY n) AS global_running_sum
            FROM generate_series(1, (SELECT max_num FROM params)) AS n
        ) AS t1
    ) AS t2
) AS t3
GROUP BY group_id
ORDER BY group_id;

方法2:递归CTE实现(逻辑更直观)

逐行判断是否需要开启新分组,适合小数据量或需要直观调试的场景:

WITH RECURSIVE params AS (
    SELECT 100 AS max_num, 20 AS sum_threshold  -- 动态参数
),
grouped_data AS (
    -- 初始行:第一个数字,初始分组ID和组和
    SELECT 
        1 AS n,
        1 AS group_id,
        1 AS current_group_sum
    FROM params
    WHERE 1 <= max_num
    UNION ALL
    -- 递归迭代后续数字
    SELECT 
        gd.n + 1,
        -- 判断是否开启新分组
        CASE 
            WHEN gd.current_group_sum + (gd.n + 1) > (SELECT sum_threshold FROM params) 
            THEN gd.group_id + 1 
            ELSE gd.group_id 
        END,
        -- 更新当前组和
        CASE 
            WHEN gd.current_group_sum + (gd.n + 1) > (SELECT sum_threshold FROM params) 
            THEN gd.n + 1 
            ELSE gd.current_group_sum + (gd.n + 1) 
        END
    FROM grouped_data gd
    JOIN params p ON gd.n < p.max_num
)
-- 聚合分组结果
SELECT 
    array_agg(n ORDER BY n) AS group_numbers,
    sum(n) AS group_sum
FROM grouped_data
GROUP BY group_id
ORDER BY group_id;

核心特点

两种方案均支持动态修改max_num和sum_threshold参数,无需改动核心逻辑,完全符合“不硬编码”的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 03:57:44