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

PostgreSQL计算三角数:使用generate_series求和及替代GROUP BY

计算三角数:无需GROUP BY保持输入顺序的SQL实现

需求背景

要计算三角数(即从0到n的所有自然数之和,等价于1到n的求和结果,加0不影响最终值),但实现中碰到两个问题:

  1. 最初尝试在CASE语句里直接对generate_series(1,n)求和,触发语法错误;
  2. 改用LATERAL关联generate_series实现求和后,因用了GROUP BY导致输出顺序和输入的n顺序不一致。

问题分析

  • 直接在CASE或SUM中嵌套generate_series不合法:generate_series返回的是多行结果集,不能直接作为SUM的参数,SQL语法不支持这种写法。
  • GROUP BY会打乱原始顺序:GROUP BY默认会对分组字段排序,导致输出的n无法保持输入时的先后顺序。

正确解决方案

通过LATERAL逐行处理每个n的求和,同时给输入数据添加行号标记原始顺序,完全不需要GROUP BY:

-- 模拟带原始顺序的输入数据
WITH input_numbers AS (
    SELECT 
        n,
        -- 生成行号标记输入时的原始顺序
        ROW_NUMBER() OVER () AS original_order
    FROM (VALUES (4), (2), (5), (1)) AS t(n)
)
SELECT
    inp.n,
    -- 1到n的和即为三角数,n=0时返回0
    COALESCE(tri_sum.sum_val, 0) AS triangular_number
FROM input_numbers inp
-- LATERAL为每个n单独生成数列并求和
LEFT JOIN LATERAL (
    SELECT SUM(x) AS sum_val
    FROM generate_series(1, inp.n) AS x
) tri_sum ON true
-- 按原始输入顺序输出结果
ORDER BY inp.original_order;

更高效的替代方案

三角数有现成的数学公式:n*(n+1)/2,用公式计算比生成数列求和效率高得多,同样能保持原始顺序:

WITH input_numbers AS (
    SELECT 
        n,
        ROW_NUMBER() OVER () AS original_order
    FROM (VALUES (4), (2), (5), (1)) AS t(n)
)
SELECT
    n,
    CASE WHEN n >=0 THEN n*(n+1)/2 ELSE 0 END AS triangular_number
FROM input_numbers
ORDER BY original_order;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 09:05:18