سكل سيرفر :لمسار شمل-التعشيش / التجمع
-
11-12-2019 - |
سؤال
لدي البيانات التي تبدو مثل:
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 في المجموع) مقابل.مجرد عقدة النظام لكل orderId
(2 في المجموع).
أي أفكار?
المحلول
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')
نصائح أخرى
للإنجاز:إليك حل بدون تحديد فرعي ، يجب أن يعمل بشكل أسرع للجداول الكبيرة.بدلا من ذلك ، يقوم بتجميع الجدول عدة مرات حيث توجد مستويات في شمل ويحدد المستوى باستخدام معرف التجميع (انظر https://technet.microsoft.com/en-us/library/bb522495 (ت = سكل. 105). أسبكس و https://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
لا تنتمي إلى StackOverflow