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

如何用T-SQL基于上一行计算值更新表中Results字段?

需求说明

需要对临时表#tmp中的Results字段进行递推计算,规则为:

  • 每个Date分组内按Month升序排列
  • 若当前行Results已有值,则直接使用该值
  • 若当前行Results为NULL,则等于上一行的Results值 + 当前行的Increment值

原始数据集的SQL定义:

DROP TABLE IF EXISTS #tmp
CREATE TABLE #tmp (
    Date DATE
    , Month INT
    , Increment FLOAT
    , Results FLOAT
)

INSERT INTO #tmp(Date, Month, Increment, Results) 
VALUES
('7/1/2022', 0, 0.0027347877960046, 0.00439631056653702)
, ('7/1/2022', 1,   0.0332610867687839, NULL)
, ('7/1/2022', 2,   0.0541567096339919, NULL)
, ('7/1/2022', 3,   0.0534245249728661, NULL)
, ('7/1/2022', 4,   0.0497604938051764, NULL)
, ('7/1/2022', 5,   0.0448266874224477, NULL)
, ('7/1/2022', 6,   0.0637221774467554, NULL)
, ('7/1/2022', 7,   0.0953341922962425, NULL)
, ('7/1/2022', 8,   0.117940928214655,  NULL)
, ('7/1/2022', 9,   0.0955895317176205, NULL)
, ('6/1/2022',  0,  0.0027347877960046, 0.00439631056653702)
, ('6/1/2022',  1,  0.0332610867687839, 0.00752724387918406)
, ('6/1/2022',  2,  0.0541567096339919, NULL)
, ('6/1/2022',  3,  0.0534245249728661, NULL)
, ('6/1/2022',  4,  0.0497604938051764, NULL)
, ('6/1/2022',  5,  0.0448266874224477, NULL)
, ('6/1/2022',  6,  0.0637221774467554, NULL)
, ('6/1/2022',  7,  0.0953341922962425, NULL)
, ('6/1/2022',  8,  0.117940928214655,  NULL)
, ('6/1/2022',  9,  0.0955895317176205, NULL)

期望的计算结果示例:

Date    Month   Increment   Results
6/1/2022    0   0.002734788 0.004396311
6/1/2022    1   0.033261087 0.007527244
6/1/2022    2   0.05415671  0.061683954
6/1/2022    3   0.053424525 0.115108478
6/1/2022    4   0.049760494 0.164868972
6/1/2022    5   0.044826687 0.20969566
6/1/2022    6   0.063722177 0.273417837
6/1/2022    7   0.095334192 0.368752029
6/1/2022    8   0.117940928 0.486692958
6/1/2022    9   0.095589532 0.582282489
7/1/2022    0   0.002734788 0.004396311
7/1/2022    1   0.033261087 0.037657397
7/1/2022    2   0.05415671  0.091814107
7/1/2022    3   0.053424525 0.145238632
7/1/2022    4   0.049760494 0.194999126
7/1/2022    5   0.044826687 0.239825813
7/1/2022    6   0.063722177 0.303547991
7/1/2022    7   0.095334192 0.398882183
7/1/2022    8   0.117940928 0.516823111
7/1/2022    9   0.095589532 0.612412643
最优实现方案

使用**递归CTE(公共表表达式)**是最直接且高效的方式,它可以按分组逐行递推计算,完美适配“用上一行结果计算当前值”的需求,同时能正确处理分组内存在多个非NULL Results的情况。

具体SQL代码如下:

WITH RecursiveCTE AS (
    -- 锚点成员:取每个Date分组中最小Month的行,保留原始Results
    SELECT 
        Date,
        Month,
        Increment,
        Results
    FROM #tmp
    WHERE Month = (SELECT MIN(Month) FROM #tmp t WHERE t.Date = #tmp.Date)

    UNION ALL

    -- 递归成员:按Month顺序,逐行计算Results
    SELECT 
        t.Date,
        t.Month,
        t.Increment,
        -- 若当前行Results不为NULL则直接用,否则用上一行Results加当前Increment
        CASE 
            WHEN t.Results IS NOT NULL THEN t.Results
            ELSE r.Results + t.Increment 
        END AS Results
    FROM #tmp t
    INNER JOIN RecursiveCTE r 
        ON t.Date = r.Date 
        AND t.Month = r.Month + 1
)
-- 输出最终结果,按Date和Month排序
SELECT 
    Date,
    Month,
    ROUND(Increment, 9) AS Increment,
    ROUND(Results, 9) AS Results
FROM RecursiveCTE
ORDER BY Date DESC, Month;

代码说明

  1. 锚点成员:筛选每个Date分组中Month最小的行,作为递推的起始点,保留原始的Results值。
  2. 递归成员:通过自连接,将当前行与同分组中Month小1的行关联,根据规则计算当前行的Results:如果当前行已有值则直接使用,否则用上一行的Results加上当前行的Increment。
  3. 最终输出:对结果按Date和Month排序,并对数值进行四舍五入,与期望结果格式一致。

替代方案:窗口函数(适用于无中间非NULL Results的场景)

如果每个Date分组中只有第一行有Results,后续全为NULL,也可以用窗口函数的累计求和实现:

SELECT 
    Date,
    Month,
    ROUND(Increment, 9) AS Increment,
    ROUND(
        FIRST_VALUE(Results) OVER (PARTITION BY Date ORDER BY Month) 
        + SUM(Increment) OVER (PARTITION BY Date ORDER BY Month ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
        - Increment, -- 减去当前行的Increment,因为第一行的Results已经包含初始值
        9
    ) AS Results
FROM #tmp
ORDER BY Date DESC, Month;

但这种方案无法处理分组内中间行存在非NULL Results的情况(比如示例中6/1/2022的Month1有值),因此递归CTE是更通用的最优解。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:43:56