SQL Server 2008:指定角色下返回值为True的列名(合并为数组)
按角色合并SQL Server中值为True的列名
嘿,我来帮你搞定这个问题!你原来的SQL语句语法有问题,EXISTS的用法完全不对,这样写会多次触发查询,导致重复返回结果,根本达不到你想要的效果。咱们换个思路,要实现按角色把值为True(对应bit类型的1)的列名合并成列表,核心思路是先把列转成行,再按角色聚合,下面给你几种实用的方案:
方案1:使用UNPIVOT + STRING_AGG(SQL Server 2017及以上)
这种方法最简洁,利用UNPIVOT操作把列转换为行,再用STRING_AGG直接合并符合条件的列名:
SELECT role, STRING_AGG(column_name, ', ') AS enabled_columns FROM Roles UNPIVOT ( is_enabled FOR column_name IN (column_1, column_2, column_3) ) AS unpivoted_data WHERE is_enabled = 1 -- 筛选值为True的列 GROUP BY role
执行后会得到你想要的结果:
| role | enabled_columns |
|---|---|
| a | column_1, column_2 |
| b | column_1, column_3 |
| c | column_3 |
方案2:使用UNION ALL + STRING_AGG(兼容更多版本)
如果你的SQL Server版本不支持UNPIVOT,可以用UNION ALL手动把每个列拆成行,再聚合:
SELECT role, STRING_AGG(column_name, ', ') AS enabled_columns FROM ( -- 逐个判断列是否为True,收集对应的列名 SELECT role, CASE WHEN column_1 = 1 THEN 'column_1' END AS column_name FROM Roles UNION ALL SELECT role, CASE WHEN column_2 = 1 THEN 'column_2' END AS column_name FROM Roles UNION ALL SELECT role, CASE WHEN column_3 = 1 THEN 'column_3' END AS column_name FROM Roles ) AS unpivoted_data WHERE column_name IS NOT NULL -- 过滤掉值为False的列(对应的column_name为NULL) GROUP BY role
方案3:兼容SQL Server 2016及更早版本(无STRING_AGG)
如果你的SQL Server版本太旧,不支持STRING_AGG,可以用STUFF + FOR XML PATH的方式来拼接字符串:
SELECT role, STUFF( ( SELECT ', ' + column_name FROM ( SELECT 'column_1' AS column_name WHERE r.column_1 = 1 UNION ALL SELECT 'column_2' WHERE r.column_2 = 1 UNION ALL SELECT 'column_3' WHERE r.column_3 = 1 ) AS cols FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 2, '' -- 去掉开头多余的", " ) AS enabled_columns FROM Roles r GROUP BY r.role, r.column_1, r.column_2, r.column_3
这几种方案都能实现你想要的效果,根据你的SQL Server版本选最合适的就行~
内容的提问来源于stack exchange,提问作者ang
相关产品推荐
相关产品推荐

