【问题标题】:SQL Server : FOR XML PATH - nesting / groupingSQL Server:FOR XML PATH - 嵌套/分组
【发布时间】:2012-07-25 21:30:03
【问题描述】:

我的数据看起来像:

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

有什么想法吗?

【问题讨论】:

    标签: sql-server for-xml-path


    【解决方案1】:
    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')
    

    【讨论】:

    • 谢谢伯特。子查询“for xml path”语句中的“type”有什么作用?
    • @jared 意思是,'将其作为 XML 数据类型返回。所以在上面的查询中,它只是将子查询作为一个小的 xml 片段返回。
    【解决方案2】:

    为了完成:这是一个没有子选择的解决方案,对于大表应该执行得更快。相反,它将表分组的次数与 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-09-29
      • 1970-01-01
      • 2020-02-24
      • 2014-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多