SQL Server中如何合并同名行的透视表结果
你当前的透视语句之所以会返回重复的用户行,是因为透视操作只是将serviceType列转成了列,但没有对用户名称进行聚合——每个原始的服务类型行都会生成一行结果,哪怕用户名称相同。要合并这些同名行,只需要在透视结果上加上GROUP BY和聚合函数(比如SUM),或者换一种更直接的方式用CASE WHEN实现透视+聚合。
方法一:透视后聚合修改后的SQL
直接在你现有透视语句的基础上,对用户名称分组并求和:
SELECT name = sFname + ' ' + sLname, SUM(advanced) AS advanced, SUM(basic) AS basic, SUM(standard) AS standard FROM ( SELECT * FROM dbName..person WHERE deleteFlag <> 'Y' ) AS tableTemp PIVOT ( COUNT(serviceType) FOR serviceType IN (advanced, basic, standard) ) AS tablePivot GROUP BY sFname + ' ' + sLname
原理很简单:透视后的结果里,同一个用户的不同行对应不同服务类型的计数(1或0),用SUM把这些行的数值相加,就能得到每个用户对应各服务类型的总次数,GROUP BY则确保每个用户只返回一行。
方法二:用CASE WHEN直接实现聚合透视(更高效)
这种方式不需要单独的透视操作,一步完成分组和统计,性能会更优:
SELECT name = sFname + ' ' + sLname, advanced = COUNT(CASE WHEN serviceType = 'advanced' THEN 1 END), basic = COUNT(CASE WHEN serviceType = 'basic' THEN 1 END), standard = COUNT(CASE WHEN serviceType = 'standard' THEN 1 END) FROM dbName..person WHERE deleteFlag <> 'Y' GROUP BY sFname + ' ' + sLname
这里利用CASE WHEN筛选出每个服务类型的行,COUNT函数会自动忽略NULL值(不匹配的CASE会返回NULL),从而统计出每个用户对应各服务类型的次数,同时GROUP BY保证用户唯一。
验证结果
两种方法都会返回你期望的合并后结果:
name | advanced | basic | standard
----------+----------+-------+---------
abby a | 1 | 1 | 0
charlie c | 0 | 1 | 1
为什么原语句的DISTINCT无效?
你原语句里的DISTINCT只是去除完全重复的行,但同一个用户的不同行(比如abby a的两行,分别对应advanced=1和basic=1)并不是完全重复的,所以DISTINCT无法合并它们,必须用GROUP BY配合聚合函数来合并数值。
内容的提问来源于stack exchange,提问作者ang

