如何在MS SQL Server中按指定门店分组汇总表列余额?
解决MS SQL Server按指定门店分组汇总并合并门店名称的问题
你提到已经试过GROUP BY、UNION但没得到满意结果,别着急,针对这个按自定义门店分组汇总的需求,我们可以通过定义分组标识+字符串聚合的方式在MS SQL Server里实现,下面给你两种可行方案:
方法一:使用CASE定义分组+STRING_AGG聚合门店名称(SQL Server 2017+)
如果你的SQL Server版本是2017或更新的,直接用STRING_AGG会非常简洁:
SELECT Code, Name, STRING_AGG(Store, ',') AS Store, SUM(Balance) AS [Total Balance By Stores] FROM ( SELECT Code, Name, Store, Balance, -- 给门店分配分组标识,把同国家的门店归为一组 CASE WHEN Store IN ('NY', 'PR', 'ST') THEN 'Group_NY_PR_ST' WHEN Store IN ('AL', 'OH') THEN 'Group_AL_OH' ELSE Store -- CH和DE单独成组 END AS GroupKey FROM YourTableName -- 替换成你的实际表名 ) AS GroupedData GROUP BY Code, Name, GroupKey ORDER BY Code, -- 按你期望的顺序排序分组 CASE GroupKey WHEN 'Group_NY_PR_ST' THEN 1 WHEN 'CH' THEN 2 WHEN 'DE' THEN 3 WHEN 'Group_AL_OH' THEN 4 END;
代码解释:
- 子查询里的
CASE是核心逻辑:我们给每个门店标记了对应的分组键,把需要合并的门店归到同一个分组下,单独的门店直接用自身名称作为分组键 - 外层通过
GROUP BY Code, Name, GroupKey按产品和分组聚合,STRING_AGG自动把同组的门店名称用逗号拼接,SUM(Balance)计算分组总余额 ORDER BY子句保证结果的分组顺序和你期望的完全一致
兼容旧版本SQL Server的方案(2016及更早)
如果你的SQL Server版本不支持STRING_AGG,可以用经典的STUFF + FOR XML PATH组合来实现字符串聚合:
-- 先通过CTE定义好分组规则 WITH GroupedData AS ( SELECT Code, Name, Store, Balance, CASE WHEN Store IN ('NY', 'PR', 'ST') THEN 'Group_NY_PR_ST' WHEN Store IN ('AL', 'OH') THEN 'Group_AL_OH' ELSE Store END AS GroupKey FROM YourTableName -- 替换成实际表名 ) SELECT gd.Code, gd.Name, -- 用STUFF+FOR XML PATH拼接门店名称 STUFF(( SELECT ',' + Store FROM GroupedData WHERE Code = gd.Code AND Name = gd.Name AND GroupKey = gd.GroupKey FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS Store, SUM(gd.Balance) AS [Total Balance By Stores] FROM GroupedData gd GROUP BY gd.Code, gd.Name, gd.GroupKey ORDER BY gd.Code, CASE gd.GroupKey WHEN 'Group_NY_PR_ST' THEN 1 WHEN 'CH' THEN 2 WHEN 'DE' THEN 3 WHEN 'Group_AL_OH' THEN 4 END;
为什么这个方案可行?
- CTE部分和第一种方法的子查询逻辑完全一致,先给门店打好分组标签
STUFF + FOR XML PATH是SQL Server旧版本里的标准字符串聚合写法:它会把同组的门店名称拼接成带前置逗号的字符串,再用STUFF去掉第一个字符的多余逗号
结果验证
这两个方案都会输出你想要的结果:
Code | Name | Store | Total Balance By Stores
56 | product1 | NY,PR,ST | 30
56 | product1 | CH | 100
56 | product1 | DE | 1000
56 | product1 | AL,OH | 20000
57 | product2 | NY,PR,ST | 30
57 | product2 | CH | 100
57 | product2 | DE | 1000
57 | product2 | AL,OH | 20000
58 | product3 | NY,PR,ST | 30
58 | product3 | CH | 100
58 | product3 | DE | 1000
58 | product3 | AL,OH | 20000
记得把代码里的YourTableName替换成你实际使用的表名哦!
内容的提问来源于stack exchange,提问作者Jirka
相关产品推荐
相关产品推荐

