2016-12-05 40 views
3

考慮下面的數據集一個XML列,我想Name分組的數據,但RoleIDRoleNamePermissionIDPermissionName值被放在一起作爲一個單XML值:如何選擇多行與T-SQL和XQuery

Name   RoleID  RoleName  PermissionID PermissionName 
--------------- ----------- ------------- ------------ --------------- 
User 1   2   Super User 1   View 
User 1   2   Super User 2   Create 
User 1   2   Super User 3   Edit 
User 1   2   Super User 4   Delete 
User 1   3   Report User 17   Execute 

所以,輸出我試圖去,應該是這個樣子:

Name  Roles 
------------ ------------------------------------------------------- 
User 1  <Roles> 
       <Role id="2" name="Super User"> 
        <Permissions> 
         <Permission id="1" name="View" /> 
         <Permission id="2" name="Create" /> 
         <Permission id="3" name="Edit" /> 
         <Permission id="4" name="Delete" /> 
        </Permissions> 
       </Role> 
       <Role id="3" name="Report User"> 
        <Permissions> 
         <Permission id="17" name="Execute" /> 
        </Permissions> 
       </Role> 
      </Roles> 

我曾嘗試以下,但它會創建一個Role行在數據集中的每個條目:

SELECT 
     U.[ID] as [Name] 
    , CONVERT(xml, (
     SELECT 
      R.[ID] as '@id' 
      , R.[Name] as '@name' 
      , CONVERT(xml, (
       SELECT 
        P.[ID] as '@id' 
       , P.[Name] as '@name' 
       FOR XML PATH('Permission') 
      )) as [Permissions] 
     FOR XML PATH('Role'), ROOT('Roles') 
    )) as [Roles] 
FROM User U 
    LEFT JOIN UserRoles UR ON 
     U.[ID] = UR.[UserID] 
    LEFT JOIN Role R ON 
     UR.[RoleID] = R.[ID] 
    LEFT JOIN RolePermissions RP ON 
     R.[ID] = RP.[RoleID] 
    LEFT JOIN Permission P ON 
     RP.[PermissionID] = P.[ID] 
WHERE 
    U.[ID] = 1234 

回答

1

我用了你的數據集,而不是作爲一個CTE(富),並通過使用嵌套選擇和集團通過獲得您想要的結果。我使用「Name」作爲用戶密鑰,因爲您的示例數據中沒有用戶ID,但您應該能夠使其與查詢一起工作。

with foo as 
(
select 
* 
from 
(values 
('User 1','2',' Super User','1','View') 
,('User 1','2',' Super User','2','Create') 
,('User 1','2',' Super User','3','Edit') 
,('User 1','2',' Super User','4','Delete') 
,('User 1','3',' Report User','17',' Execute') 
) foo(Name,RoleID,RoleName,PermissionID,PermissionName) 
) 

select 
    Name, 
    cast((
    SELECT 
     B.RoleID as '@id' 
     ,B.RoleName as '@name' 
     ,cast((select PermissionID as '@id',PermissionName as '@name' 
     from Foo C 
     where c.RoleID=b.RoleID 
       and c.Name=a.Name 
     for xml path('Permission') 
    ) as xml) Permissions 
    FROM foo B 
    group by 
     B.RoleID 
     ,B.RoleName 
    for xml path('Role'),root('Roles') 
    ) as xml) Roles 
from 
foo a 
group by Name 

我沒有測試過下面的查詢,但它應該是非常接近的東西在你的表工作:

select 
    U.ID as [Name], 
    cast((
    SELECT 
     R.[ID] as '@id' 
     , R.[Name] as '@name' 
     ,cast(
     (select 
      P.[ID] as '@id' 
      , P.[Name] as '@name' 
     from RolePermissions RP 
      LEFT JOIN Permission P ON 
      RP.[PermissionID] = P.[ID] 
     where R.[ID] = RP.[RoleID] 
     for xml path('Permission') 
    ) as xml) [Permissions] 
    FROM UserRoles UR 
     Left Join Role R 
     ON UR.[RoleID] = R.[ID] 
     where U.[ID] = UR.[UserID] 
    group by 
     R.[ID] 
     ,R.[Name] 
    for xml path('Role'),root('Roles') 
    ) as xml) [Roles] 
from 
User U 
group by ID 
WHERE 
    U.[ID] = 1234 
+1

AFAICT演員陣容到XML是沒有必要的,如果你指定'FOR XML PATH('角色'),ROOT('角色'),TYPE''。參考:[FOR XML查詢中的TYPE指令](https://msdn.microsoft.com/zh-cn/library/ms190025.aspx):*請求通過指定FOR XML查詢的結果作爲xml數據類型返回TYPE指令*。 –

+0

PS:您可以在[RexTester](http://rextester.com/l/sql_server_online_compiler)進行快速測試。查看我的個人資料以獲取更有趣的內容 –