Sql server sql连接角色

Sql server sql连接角色,sql-server,Sql Server,我有一个userdata表,userdata和角色之间的n到m关系,还有一个角色表 例如: | Userdata | UserRolesRel | Roles | |------------|----------------|--------------| | Id Nick |Id_User Id_Role | Id Name | | 1 John | 1 1 | 1 Admin | | 2 Frank|

我有一个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)

StackOverflow中详细介绍了这一点:

测试表和数据

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路径(“”)
技巧:

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

如果大于等于SQL Server 2017、SQL Server Vnext、SQL Azure,则可以使用字符串和分组方式,如下所示

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')