SQL Server 2012多列统计Yes/No/Null总数问题求助
解决SQL Server多列统计Yes/No/Null总数的问题
嘿,我来帮你搞定这个统计问题!首先咱们先明确你的需求:要把names表中所有以test开头的列里的yes、no、null数量分别汇总,最终得到一行结果显示总数。
先复盘下你原来的问题
你之前的CTE写法只针对test1列做了统计,而且GROUP BY Inspection1Type应该是笔误(应该是test1?),这种写法会把test1的不同值分组,没办法跨列汇总所有test开头字段的数据,而且如果直接复制代码加test2、test3的话,会因为别名重复报错,这确实不是正确的思路。
推荐方案:用UNPIVOT逆透视(最简洁)
SQL Server的UNPIVOT可以把多列转换成多行,这样我们就能统一统计所有test列的数值了,不管你有10列还是更多列,都能轻松处理。
静态版本(适合已知所有test列的情况)
假设你的test列是test1到test10,直接写死列名即可:
SELECT SUM(CASE WHEN answer = 'yes' THEN 1 ELSE 0 END) AS yes, SUM(CASE WHEN answer = 'no' THEN 1 ELSE 0 END) AS no, SUM(CASE WHEN answer IS NULL THEN 1 ELSE 0 END) AS [null] FROM names UNPIVOT ( answer FOR test_columns IN (test1, test2, test3, test4, test5, test6, test7, test8, test9, test10) ) AS unpvt;
执行后就能得到你想要的结果:yes = 4, no = 2, null = 2。
动态版本(适合列数不确定或后续会新增的情况)
如果以后可能会加test11、test12这类列,手动改SQL太麻烦,咱们可以用动态SQL自动获取所有test开头的列:
DECLARE @cols NVARCHAR(MAX); DECLARE @sql NVARCHAR(MAX); -- SQL Server 2012用FOR XML PATH拼接列名(2017+可用STRING_AGG) SELECT @cols = STUFF(( SELECT ', ' + QUOTENAME(column_name) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'names' AND column_name LIKE 'test%' FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 2, ''); -- 构建动态统计SQL SET @sql = N' SELECT SUM(CASE WHEN answer = ''yes'' THEN 1 ELSE 0 END) AS yes, SUM(CASE WHEN answer = ''no'' THEN 1 ELSE 0 END) AS no, SUM(CASE WHEN answer IS NULL THEN 1 ELSE 0 END) AS [null] FROM names UNPIVOT ( answer FOR test_columns IN (' + @cols + N') ) AS unpvt;'; -- 执行动态SQL EXEC sp_executesql @sql;
这个脚本会自动读取所有test开头的列,不用手动维护列名列表。
备选方案:硬写所有列的CASE WHEN(适合列数很少的情况)
如果不想用UNPIVOT,也可以直接把每列的统计结果加起来,虽然代码冗余但逻辑简单:
SELECT -- 汇总所有test列的yes数量 SUM(CASE WHEN test1 = 'yes' THEN 1 ELSE 0 END) + SUM(CASE WHEN test2 = 'yes' THEN 1 ELSE 0 END) + SUM(CASE WHEN test3 = 'yes' THEN 1 ELSE 0 END) + SUM(CASE WHEN test4 = 'yes' THEN 1 ELSE 0 END) + -- 继续添加test5到test10的CASE WHEN SUM(CASE WHEN test10 = 'yes' THEN 1 ELSE 0 END) AS yes, -- 汇总no的数量 SUM(CASE WHEN test1 = 'no' THEN 1 ELSE 0 END) + SUM(CASE WHEN test2 = 'no' THEN 1 ELSE 0 END) + ... + SUM(CASE WHEN test10 = 'no' THEN 1 ELSE 0 END) AS no, -- 汇总null的数量 SUM(CASE WHEN test1 IS NULL THEN 1 ELSE 0 END) + SUM(CASE WHEN test2 IS NULL THEN 1 ELSE 0 END) + ... + SUM(CASE WHEN test10 IS NULL THEN 1 ELSE 0 END) AS [null] FROM names;
结果验证
用你提供的测试数据(bob和john两行),不管用哪种方案,都会得到:
| yes | no | null |
|---|---|---|
| 4 | 2 | 2 |
完全符合你的预期结果!
内容的提问来源于stack exchange,提问作者sql2015
相关产品推荐
相关产品推荐

