2012-07-25 14 views
15

ように私に見えるのデータを持っている:私はこのようなデータを返すために、SQL ServerのT-SQLクエリを書きたいSQL Serverの:XMLパスの - のネスト/グループ化

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 

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

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

をしかし、それは私の各行についてOrderノードを提供します(6:私は使用してXMLでクエリを返す試みた

合計)と各ノードのオーダーノードとの合計(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 for'は 'xml path'文のために何をしますか? – jared

+4

@jaredこれは、「これをXMLデータ型として返す」という意味です。上のクエリでは、サブクエリを小さなxmlフラグメントとして返すだけです。 – Bert

+0

恐ろしい。ありがとう! – jared

0

補完用:ここでは、大きなテーブルの方が高速に実行する必要があります。 (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を参照)がレベルはXMLであり、GROUPING_IDとレベルを特定してその代わりに、グループテーブル何度でも:

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