26

我的数据看起来像:

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 个)。

有任何想法吗?

4

2 回答 2

38
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')
于 2012-07-25T22:16:39.653 回答
4

为了完成:这是一个没有子选择的解决方案,对于大表应该执行得更快。相反,它将表分组的次数与 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
于 2017-08-09T09:35:45.143 回答