问题:系统的用户T_User拥有多个角色,在T_UserRole表进行关联,角色表为T_Role。
现在要求取出UserList;并取出每个User的角色信息,拼接成字符串类型。
预备知识:
T_UserRole 表结构:
STUFF字符串函数是将字符串插入到另一个字符串中。它会删除开始位置第一个字符串中的指定长度的字符,然后将第二个字符串插入到开始位置的第一个字符串中,语法如下。
STUFF(<character_expression>,<开始>,<长度>,<character_expression>)
<character_expression>参数是给定的字符串数据,可以是字符或二进制数据的常量,变量或列。<start>参数是一个整数值,指定开始删除和插入的位置,可以是BIGINT类型。如果<开始>或<长度>参数为负数,则返回NULL字符串。如果<start>参数比第一个<character_expression>长,则返回一个NULL字符串。 <length>参数可以是BIGINT类型,它是一个整数,指定要删除的字符数。如果<length>比第一个<character_expression>长,则删除发生到最后一个<character_expression>中的最后一个字符。
FOR XML PATH 可以将查询结果根据行输出成XML格式。
可以参考:https://www.cnblogs.com/yasuo2/p/6433697.html
具体解析:
1. (关键)中间橙色部分代码,是将多行转为XML格式的内容。distinct 去重。运行结果:
2. 黑色部分代码,是截取掉前面的“,“字符,STUFF字符串函数。
// 简化一下 // tempXml = ,64,65这样就是我们要的数据了
// 给定的字符串为@tempXml,从第1个位置开始,删除长度为1,在前面插入''(这里无字符),结果输出64,65。 select stuff({tempXml}, 1, 1, ''))
3. 蓝色部分,不为空判断。
最终代码
// 最终代码
SELECT tu.Id, tu.Name as UserName,
ISNULL((select stuff((select distinct ',' + CONVERT(varchar, mur.RoleId)
from T_UserRole mur RIGHT JOIN T_User tus ON mur.UserId = tus.Id AND mur.IsDel = 0 AND mur.IsUsed = 1 LEFT JOIN T_Role role ON role.Id = mur.RoleId where tus.IsDel = 0 and tus.Id = tu.Id and role.IsDel = 0 and role.IsUsed = 1 FOR XML PATH ('')), 1, 1, '')), 0) as RoleIds,
(select stuff((select distinct ',' + CONVERT(varchar, role.Name) from T_UserRole mur RIGHT JOIN T_User tus ON mur.UserId = tus.Id AND mur.IsDel = 0 AND mur.IsUsed = 1 LEFT JOIN T_Role role ON role.Id = mur.RoleId AND role.IsDel = 0 AND role.IsUsed = 1 where tus.IsDel = 0 and tus.Id = tu.Id and role.IsDel = 0 and role.IsUsed = 1 FOR XML PATH ('')), 1, 1, '')) as RoleNames from T_User tu where tu.IsDel = 0 ORDER BY tu.CreateTime DESC
运行结果: