SQL中SUMIF等效实现:计算发票明细行总数量及占比
解决方案:使用窗口函数实现分组求和并保留明细
你的需求核心是在保留所有明细行的前提下,计算同一发票(Invoice)+商品(Item)维度的总数量,再计算当前行数量占该维度总数量的百分比,这完全可以通过SQL的窗口函数实现,不需要用CASE+GROUP BY,窗口函数就相当于Excel里的SUMIF功能,且不会丢失明细。
假设你的表名为invoice_items,对应的SQL语句如下:
SELECT Invoice, Item, Batch, Quantity, -- 计算同一Invoice+Item下的总数量 SUM(Quantity) OVER (PARTITION BY Invoice, Item) AS "Tot inv Qty", -- 计算占比并格式化为百分比 CONCAT(ROUND((Quantity * 100.0) / SUM(Quantity) OVER (PARTITION BY Invoice, Item), 0), '%') AS "%Inv" FROM invoice_items;
关键部分说明:
SUM(Quantity) OVER (PARTITION BY Invoice, Item):这是窗口函数的核心逻辑,PARTITION BY指定了分组维度(发票号+商品编码),SUM(Quantity)会对每个分组内的所有数量求和,同时保留每一行的原始明细数据,不会像普通GROUP BY那样合并行。- 百分比计算:先通过
(Quantity * 100.0) / 分组总数量得到占比数值,用ROUND取整后,再用CONCAT拼接百分号,得到类似25%的格式。如果需要保留小数位,可调整ROUND的第二个参数(比如ROUND(..., 1)会保留一位小数)。
为什么普通GROUP BY不适用?
普通的GROUP BY Invoice, Item会把同一发票+商品的行合并成一行,直接丢失Batch和单条Quantity的明细数据,而窗口函数的PARTITION BY是在不改变原始行结构的前提下,对指定分组做聚合计算,完美匹配你的需求。
内容的提问来源于stack exchange,提问作者Gadwood
相关产品推荐
相关产品推荐

