我有一个userdata表,userdata和角色之间的n到m关系,以及一个角色表。
示例:
| Userdata | UserRolesRel | Roles |
|------------|----------------|--------------|
| Id Nick |Id_User Id_Role | Id Name |
| 1 John | 1 1 | 1 Admin |
| 2 Frank| 1 2 | 2 User |
| | 1 3 | 3 Reader|
| | 2 2 | |
现在我想检索这样的数据
| Nick | Roles |
|---------|-------------------|
| John | Admin,User,Reader |
| Frank | User |
我怎么能成功呢?
(我正在使用sql server 2008)
答案 0 :(得分:2)
StackOverflow中详细介绍了这一点:
答案 1 :(得分:1)
测试表和数据
declare @UserData table
(
Id int,
Nick varchar(10)
)
declare @UserRolesRel table
(
Id_User int,
Id_Role int
)
declare @Roles table
(
Id int,
Name varchar(10)
)
insert into @UserData values(1, 'John'),(2, 'Frank')
insert into @UserRolesRel values(1,1),(1,2),(1,3),(2,2)
insert into @Roles values(1, 'Admin'),(2, 'User'),(3, 'Reader')
使用FOR XML PATH('')
技巧:
select UD.Nick,
stuff((select ', '+R.Name
from @Roles as R
inner join @UserRolesRel as URR
on R.Id = URR.Id_Role
where URR.Id_User = UD.Id
for xml path(''), type).value('.', 'nvarchar(max)'), 1, 2, '') as Roles
from @UserData as UD
使用递归cte:
的更长版本;with cte1 as
(
select UD.Nick,
R.Name as RoleName,
URR.Id_User,
URR.Id_Role,
row_number() over(partition by URR.Id_User order by URR.Id_Role) as rn
from @UserRolesRel as URR
inner join @UserData as UD
on URR.Id_User = UD.Id
inner join @Roles as R
on URR.Id_Role = R.Id
),
cte2 as
(
select C.Nick,
cast(C.RoleName as varchar(max)) as Roles,
C.Id_User,
C.rn
from cte1 as C
where C.rn = 1
union all
select C1.Nick,
C2.Roles + ', '+C1.RoleName as Roles,
C1.Id_User,
C1.rn
from cte1 as C1
inner join cte2 as C2
on C1.Id_User = C2.Id_User and
C1.rn = C2.rn + 1
)
select C2.Nick,
C2.Roles
from cte2 as C2
inner join (
select Id_User, max(rn) as rn
from cte1
group by Id_User
) as M
on M.rn = C2.rn and
M.Id_User = C2.Id_User
答案 2 :(得分:0)
如果是> = SQL Server 2017,SQL Server Vnext,SQL Azure,您可以使用STRING_AGG并按以下分组
select u.Nick, [Roles] = string_agg(r.Name, ',') from @userdata u
inner join @UserRolesRel urr on u.id = urr.Id_User
inner join @Roles r on urr.Id_Role = r.Id
group by u.Nick
您的输入表格:
declare @UserData table(Id int,Nick varchar(10))
declare @UserRolesRel table(Id_User int, Id_Role int)
declare @Roles table (Id int, Name varchar(10) )
insert into @UserData values(1, 'John'),(2, 'Frank')
insert into @UserRolesRel values(1,1),(1,2),(1,3),(2,2)
insert into @Roles values(1, 'Admin'),(2, 'User'),(3, 'Reader')