我有一个角色与权限表:
role | permission
r1 | p1
r2 | p1
r2 | p2
r3 | p1
r3 | p2
r3 | p3
我想要的是一个输出表,其中列是(角色,然后是每个权限)。如果表中存在权限/角色对,我想要1,它不存在,我想要一个0。
这是输出:
role | p1 | p2 | p3
r1 | 1 | 0 | 0
r2 | 1 | 1 | 0
r3 | 1 | 1 | 1
这很容易,但这里有踢球者...... 角色或权限都不是固定长度,可以随时添加新的角色,因此我需要考虑这一点。
由于SQL的性质,我不认为这是可能的,但我想我会问。
答案 0 :(得分:1)
您没有指定您正在使用的RDBMS - 所以这里是MySQL和SQL Server的解决方案。
<强> MySQL的:强>
这是PIVOT
,但MySQL没有PIVOT
函数,因此您需要使用聚合函数和CASE
语句复制它。
静态版本 - 您事先知道所有值的地方:
select role,
sum(case when permission = 'p1' then 1 else 0 end) p1,
sum(case when permission = 'p2' then 1 else 0 end) p2,
sum(case when permission = 'p3' then 1 else 0 end) p3
from yourtable
group by role;
如果您事先不知道要转向列的值,则可以使用预准备语句:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(case when permission = ''',
permission,
''' then 1 else 0 end) AS ',
permission
)
) INTO @sql
FROM yourtable;
SET @sql = CONCAT('SELECT role, ', @sql, '
FROM yourtable
GROUP BY role');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SQL Server:
在sql server中有一个PIVOT
函数,您可以对值进行硬编码或使用动态sql。
静态版本:
select *
from
(
select role, permission
from yourtable
) src
pivot
(
count(permission)
for permission in ([p1], [p2], [p3])
) piv;
动态版本:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(permission)
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT role, ' + @cols + ' from
(
select role, permission
from yourtable
) x
pivot
(
count(permission)
for permission in (' + @cols + ')
) p '
execute(@query)
所有版本的结果是:
| ROLE | P1 | P2 | P3 |
-----------------------
| r1 | 1 | 0 | 0 |
| r2 | 1 | 1 | 0 |
| r3 | 1 | 1 | 1 |