2012-07-25 52 views
15

我有一個看起來數據,如:SQL服務器:FOR XML PATH - 嵌套/分組

OrderID CustomerID ItemID ItemName 
10000 1234  111111 Product A 
10000 1234  222222 Product B 
10000 1234  333333 Product C 
20000 5678  111111 Product A 
20000 5678  222222 Product B 
20000 5678  333333 Product C 

我想要寫SQL Server中的T-SQL查詢返回這樣的數據:

<Root> 
    <Order> 
    <OrderID>10000</OrderID> 
    <CustomerID>1234</CustomerID> 
    <LineItem> 
     <ItemID>11111</ItemId> 
     <ItemName>Product A</ItemName> 
    </LineItem> 
    <LineItem> 
     <ItemID>22222</ItemId> 
     <ItemName>Product B</ItemName> 
    </LineItem> 
    <LineItem> 
     <ItemID>33333</ItemId> 
     <ItemName>Product B</ItemName> 
    </LineItem> 
    </Order> 
    <Order> 
    <OrderID>20000</OrderID> 
    <CustomerID>5678</CustomerID> 
    <LineItem> 
     <ItemID>11111</ItemId> 
     <ItemName>Product A</ItemName> 
    </LineItem> 
    <LineItem> 
     <ItemID>22222</ItemId> 
     <ItemName>Product B</ItemName> 
    </LineItem> 
    <LineItem> 
     <ItemID>33333</ItemId> 
     <ItemName>Product B</ItemName> 
    </LineItem> 
    </Order> 
</Root> 

我試着使用XML返回查詢:

FOR XML PATH ('Order'), root ('Root') 

但是,這讓我對每一行Order節點(6總數),而不是每個orderId(總共2個)的訂單節點。

任何想法?

回答

24
select 
    OrderID, 
    CustomerID, 
    (
     select 
     ItemID, 
     ItemName 
     from @Orders rsLineItem 
     where rsLineItem.OrderID = rsOrders.OrderID 
     for xml path('LineItem'), type 
    ) 
from (select distinct OrderID, CustomerID from @Orders) rsOrders 
FOR XML PATH ('Order'), root ('Root') 
+1

謝謝伯特。 'type'在子查詢'xml path'語句中做什麼? – jared 2012-07-25 23:05:10

+4

@jared它表示'將此數據返回爲XML數據類型。'所以在上面的查詢中,它只是將子查詢作爲一個小的xml片段返回。 – Bert 2012-07-25 23:08:02

+0

太棒了。謝謝! – jared 2012-07-25 23:22:57

0

完成:這是一個沒有子選擇的解決方案,應該對大表執行更快。相反,它團體表多次有在XML層次和標識與GROUPING_ID水平(見https://technet.microsoft.com/en-us/library/bb522495(v=sql.105).aspxhttps://docs.microsoft.com/en-us/sql/relational-databases/xml/use-explicit-mode-with-for-xml):

with rsOrders as (
    select '10000' OrderID, '1234' CustomerID, '111111' ItemID, 'Product A' ItemName union 
    select '10000' orderId, '1234' customerID, '222222' itemID, 'Product B' ItemName union 
    select '10000' orderId, '1234' customerID, '333333' itemID, 'Product C' ItemName union 
    select '20000' orderId, '5678' customerID, '111111' itemID, 'Product A' ItemName union 
    select '20000' orderId, '5678' customerID, '222222' itemID, 'Product B' ItemName union 
    select '20000' orderId, '5678' customerID, '333333' itemID, 'Product C' ItemName 
) 
select case 
     when GROUPING_ID(ItemID) = 0 then 3 
     when GROUPING_ID(OrderID) = 0 then 2 
     else 1 
     end as tag, 
     case 
      when GROUPING_ID(ItemID) = 0 then 2 
     when GROUPING_ID(OrderID) = 0 then 1 
     else null 
     end as parent, 
     null  as 'Root!1', 
     OrderID as 'Order!2!OrderID!element', 
     CustomerID as 'Order!2!CustomerID!element', 
     ItemID  as 'LineItem!3!ItemID!element', 
     ItemName as 'LineItem!3!ItemName!element' 
    from rsOrders 
group by grouping sets ((), (OrderID, CustomerID), (OrderID, CustomerID, ItemID, ItemName)) 
order by OrderID, CustomerID, ItemID, ItemName 
    for xml explicit, type