T-SQL 循环遍历两个表

Cin*_*dro -1 sql t-sql sql-server stored-procedures sql-server-2016

我一直无法找到解决以下困境的可行解决方案。

我正在使用 SQL Server 2016 并在数据库中有下面显示的 2 个表。

Users 桌子:

Id   Name
----------
1    Lisa
2    Paul
3    John
4    Mike
5    Tom
Run Code Online (Sandbox Code Playgroud)

Role 桌子:

Id   UserId   Role
------------------------
1    3        Manager
2    2,4,5    Developer
3    1        Designer
Run Code Online (Sandbox Code Playgroud)

我正在寻找循环遍历Role表的T-SQL 代码,提取UserIds 并Id从Users表中检索每个的关联名称。

所以循环结果看起来像这样:

John
Paul,Mike,Tom
Lisa
Run Code Online (Sandbox Code Playgroud)

Jay*_*pta 5

对于 SQL 服务器 2017

SELECT R1.Id,STRING_AGG(U.Name , ','),R1.Role
FROM Users U
INNER JOIN
(
SELECT R.Id,S.value AS UserId,R.Role
FROM Role R
     CROSS APPLY STRING_SPLIT (UserID, ',') S
) R1
ON U.Id=R1.UserId
GROUP BY R1.ID,R1.Role
ORDER BY R1.ID;
Run Code Online (Sandbox Code Playgroud)

或者

对于 SQL SERVER 2016

WITH CTE AS
(
SELECT R2.ID,U.Name,R2.UserId,R2.Role
FROM Users U
INNER JOIN
(
SELECT R.Id,S.value AS UserId,R.Role
FROM Role R
     CROSS APPLY STRING_SPLIT (UserID, ',') S
)R2
ON U.id=R2.UserId
)
SELECT DISTINCT R1.Id,
       STUFF((
          SELECT ',' + name
          FROM CTE R3
          WHERE R1.Role = R3.Role
          FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS NAME
          ,R1.Role
FROM CTE AS R1;
Run Code Online (Sandbox Code Playgroud)

或者

对于旧版本

With CTE AS
(
SELECT r.id,
       u.name, 
       r.Role
FROM Users u 
INNER JOIN Role r
ON ',' + CAST(r.Userid AS NVARCHAR(20)) + ',' like '%,' + CAST(u.id AS NVARCHAR(20)) + ',%'
)
SELECT DISTINCT id,
          STUFF((
          SELECT ',' + name
          FROM CTE md
          WHERE T.Role = md.Role
          FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS NAME,
          Role
FROM
CTE AS T
ORDER BY id
Run Code Online (Sandbox Code Playgroud)

输出

id  NAME            Role
1   John            Manager
2   Paul,Mike,Tom   Developer
3   Lisa            Designer
Run Code Online (Sandbox Code Playgroud)

演示

http://sqlfiddle.com/#!18/04a2d/69