MySQL实现按供应商分组重置的累计求和(Running Total)问题咨询
分组累计Paid值实现方案
你原来的写法只维护了全局累计变量,没有对Vendor做变更判断,因此跨供应商时不会重置累计值。你可以根据你的MySQL版本选择以下两种实现方式:
方案1:MySQL 8.0及以上版本(推荐,窗口函数实现)
直接用开窗函数自带的分区逻辑即可实现分组内累计,性能和稳定性都优于变量写法:
SELECT InvYear, InvQuarter, InvDesc1, InvDesc2, Vendor, Paid, Billed, SUM(Paid) OVER ( PARTITION BY Vendor ORDER BY InvYear, InvQuarter, InvDesc1, InvDesc2 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS Paid_cum FROM Vendor;
逻辑说明:
PARTITION BY Vendor:按Vendor字段分组,每个分组单独计算累计值ORDER BY:指定分组内的累计顺序,你可以根据业务需求调整排序规则ROWS BETWEEN ...:明确累计范围为分组内第一行到当前行,避免窗口默认规则带来的统计偏差
方案2:MySQL 5.x及更低版本(兼容用户变量实现)
如果你的数据库版本不支持窗口函数,可以调整原变量写法,新增变量记录上一行的Vendor值,遇到Vendor变更时自动重置累计:
-- 初始化累计变量和上一个Vendor记录变量 SET @cum := 0, @prev_vendor := ''; SELECT InvYear, InvQuarter, InvDesc1, InvDesc2, Vendor, Paid, Billed, @cum := IF(Vendor = @prev_vendor, @cum + Paid, Paid) AS Paid_cum, @prev_vendor := Vendor -- 更新上一个Vendor值供下一行判断,不需要该字段可嵌套外层查询过滤 FROM Vendor -- 必须先按Vendor排序,保证同供应商的行连续排列,否则变量判断会出错 ORDER BY Vendor, InvYear, InvQuarter, InvDesc1, InvDesc2;
如果不需要显示@prev_vendor := Vendor这列,可以在外层再嵌套一层查询,只保留需要的字段即可。
内容的提问来源于stack exchange,提问作者jwa1107
相关产品推荐
相关产品推荐

