如何实现按CasinoID分区、基于唯一GameID的累计金额计算?
实现按CasinoID分区、GameID金额替换式累计求和的SQL方案
核心思路
要实现「同一CasinoID下,每个GameID仅保留最新金额并累计总和」,本质是每次遇到重复GameID时,用当前金额替换该GameID之前的金额,而非累加。可以通过窗口函数结合条件判断高效实现:
- 用
LAG()获取同一GameID上一次的金额,以及上一条记录的累计总额 - 通过
CASE分支处理两种场景:首次出现的GameID直接累加;重复出现的GameID则用「上一次累计总额 - 旧金额 + 新金额」完成替换更新
正确SQL实现
WITH prev_data AS ( SELECT CasinoID, GameID, Amount, Date, -- 获取当前GameID上一次出现的金额 LAG(Amount) OVER (PARTITION BY CasinoID, GameID ORDER BY Date) AS prev_game_amount, -- 获取同一CasinoID下上一条记录的累计总额 LAG(running_total) OVER (PARTITION BY CasinoID ORDER BY Date) AS prev_total FROM ( -- 先按CasinoID+Date排序,初始化基础数据 SELECT CasinoID, GameID, Amount, Date, 0 AS running_total FROM your_table ORDER BY CasinoID, Date ) t ) SELECT CasinoID, GameID, Amount, Date, CASE -- 首次出现的GameID:累加当前金额到之前的累计(无之前累计则直接取当前金额) WHEN prev_game_amount IS NULL THEN COALESCE(prev_total, 0) + Amount -- 重复出现的GameID:用新金额替换旧金额,更新累计总额 ELSE prev_total - prev_game_amount + Amount END AS TARGETAMOUNT FROM prev_data ORDER BY CasinoID, Date;
错误写法分析
- 第一种写法
Sum(amount) over (partition by CasinoID order by cast(date as date)):会累加所有金额,包括同一GameID的重复值,无法实现「替换」逻辑,导致累计总额虚高。 - 第二种写法
Sum(amount) over (partition by CasinoID, GameID order by cast(date as date)):仅在CasinoID+GameID的分区内求和,无法跨GameID计算全局累计总额,不符合需求。
内容的提问来源于stack exchange,提问作者lsj
相关产品推荐
相关产品推荐

