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

SQL Server:基于FuelIndicator列的特定切换场景累计值计算

解决SQL Server中FuelIndicator状态切换的累计值计算问题

我来帮你搞定这个需求——当FuelIndicator从Not Reserve切换到Reserve时,把切换前连续的Not Reserve记录的FuelAmt累加至切换后的第一条Reserve记录里,同时移除所有Not Reserve记录。我们可以用SQL Server的窗口函数来优雅实现这个逻辑,下面是具体步骤和代码:

实现思路

  1. 标记连续的Not Reserve分组:用LAG和LEAD窗口函数识别连续的Not Reserve块,以及这些块之后的第一条Reserve记录。
  2. 计算分组累计值:对每个连续的Not Reserve块计算FuelAmt的总和,并关联到对应的目标Reserve记录。
  3. 合并生成最终结果:保留所有Reserve记录,将对应分组的累计值加到目标Reserve的FuelAmt上,过滤掉Not Reserve记录。

完整SQL代码

-- 替换YourTableName为你的实际表名
WITH CTE_Grouped AS (
    -- 第一步:标记连续NotReserve的分组,以及切换到Reserve的节点
    SELECT 
        *,
        -- 标记当前行是否是连续NotReserve块的起始行
        CASE 
            WHEN FuelIndicator = 'Not Reserve' 
                 AND LAG(FuelIndicator, 1, '') OVER (ORDER BY FuelDate) != 'Not Reserve'
            THEN 1 
            ELSE 0 
        END AS IsStartOfNotReserve,
        -- 标记当前行是否是NotReserve块的最后一行,且下一行是Reserve
        CASE 
            WHEN FuelIndicator = 'Not Reserve' 
                 AND LEAD(FuelIndicator, 1, '') OVER (ORDER BY FuelDate) = 'Reserve'
            THEN 1 
            ELSE 0 
        END AS IsEndOfNotReserve,
        -- 给每个连续的NotReserve块分配唯一组ID
        SUM(CASE 
                WHEN FuelIndicator = 'Not Reserve' 
                     AND LAG(FuelIndicator,1,'') OVER (ORDER BY FuelDate) != 'Not Reserve'
                THEN 1 
                ELSE 0 
            END) OVER (ORDER BY FuelDate ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS NotReserveGroupID
    FROM YourTableName
),
CTE_NotReserveTotals AS (
    -- 第二步:计算每个NotReserve组的总FuelAmt,以及对应的目标Reserve记录日期
    SELECT 
        NotReserveGroupID,
        SUM(FuelAmt) AS TotalNotReserveFuel,
        -- 获取该组之后的第一条Reserve记录的日期
        MIN(LEAD(FuelDate, 1) OVER (PARTITION BY NotReserveGroupID ORDER BY FuelDate)) AS TargetReserveDate
    FROM CTE_Grouped
    WHERE FuelIndicator = 'Not Reserve'
    GROUP BY NotReserveGroupID
)
-- 第三步:合并结果,累加对应的值并保留Reserve记录
SELECT 
    t.FuelDate,
    t.FilledBy,
    t.KMSreading,
    -- 对目标Reserve记录累加NotReserve的总和,其他Reserve保留原值
    t.FuelAmt + ISNULL(nrt.TotalNotReserveFuel, 0) AS FuelAmt,
    t.FuelPrice,
    t.Vehicle,
    t.FuelIndicator
FROM YourTableName t
LEFT JOIN CTE_NotReserveTotals nrt 
    ON t.FuelDate = nrt.TargetReserveDate
WHERE t.FuelIndicator = 'Reserve' -- 仅保留Reserve类型的记录
ORDER BY t.FuelDate;

代码说明

  • CTE_Grouped:通过窗口函数识别连续的Not Reserve块,用NotReserveGroupID将同一连续块的记录归为一组,同时标记出块的结束节点(即下一行是Reserve的Not Reserve记录)。
  • CTE_NotReserveTotals:计算每个NotReserve组的FuelAmt总和,并找到该组之后的第一条Reserve记录的日期,作为累加的目标。
  • 最终查询:左连接两个CTE,将目标Reserve记录的FuelAmt加上对应组的总和,同时只保留Reserve类型的记录,完美匹配你的预期输出。

用你的示例数据测试这段代码,会得到和你给出的预期结果完全一致的输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:50:17