T-SQL صفوف صف أكثر فعالية إلى العمود؟ crosstab لمسار XML ، المحور
-
26-09-2019 - |
سؤال
أنا أبحث عن الطريقة الأكثر أداء لتحويل الصفوف إلى أعمدة. لدي شرط لإخراج محتويات DB (وليس المخطط الفعلي أدناه ، ولكن المفهوم متشابه) في كل من التنسيقات الثابتة والتنسيقات المحددة. يمنحني الاستعلام أدناه لـ XML Path النتيجة التي أريدها ، ولكن عند التعامل مع أي شيء آخر غير الكميات الصغيرة من البيانات ، يمكن أن يستغرق وقتًا طويلاً.
select orderid
,REPLACE(( SELECT ' ' + CAST(ProductId as varchar)
FROM _details d
WHERE d.OrderId = o.OrderId
ORDER BY d.OrderId,d.DetailId
FOR XML PATH('')
),' ','') as Products
from _orders o
لقد نظرت إلى المحور ولكن معظم الأمثلة التي وجدتها هي تجميع المعلومات. أريد فقط أن أجمع بين صفوف الأطفال وأخذها على الوالد.
أود أن أشير أيضًا إلى أنني لست بحاجة إلى التعامل مع أسماء الأعمدة إما لأن إخراج صفوف الأطفال سيكون إما سلسلة عرض ثابت أو سلسلة محددة.
على سبيل المثال ، بالنظر إلى الجداول التالية:
OrderId CustomerId
----------- -----------
1 1
2 2
3 3
DetailId OrderId ProductId
----------- ----------- -----------
1 1 100
2 1 158
3 1 234
4 2 125
5 3 101
6 3 105
7 3 212
8 3 250
للحصول على طلب أحتاج إلى الإخراج:
orderid Products
----------- -----------------------
1 100 158 234
2 125
3 101 105 212 250
أو
orderid Products
----------- -----------------------
1 100|158|234
2 125
3 101|105|212|250
أفكار أو اقتراحات؟ أنا أستخدم SQL Server 2K5.
مثال الإعداد:
create table _orders (
OrderId int identity(1,1) primary key nonclustered
,CustomerId int
)
create table _details (
DetailId int identity(1,1) primary key nonclustered
,OrderId int
,ProductId int
)
insert into _orders (CustomerId)
select 1
union select 2
union select 3
insert into _details (OrderId,ProductId)
select 1,100
union select 1,158
union select 1,234
union select 2,125
union select 3,105
union select 3,101
union select 3,212
union select 3,250
CREATE CLUSTERED INDEX IX_CL__orders on _orders(OrderId)
CREATE NONCLUSTERED INDEX IX_NCL__orders on _orders(OrderId)
INCLUDE (CustomerId)
CREATE CLUSTERED INDEX IX_CL_details on _details(OrderId)
CREATE NONCLUSTERED INDEX IX_NCL_details on _details(OrderId)
INCLUDE (DetailId,ProductId)
باستخدام مسار XML:
select orderid
,REPLACE(( SELECT ' ' + CAST(ProductId as varchar)
FROM _details d
WHERE d.OrderId = o.OrderId
ORDER BY d.OrderId,d.DetailId
FOR XML PATH('')
),' ','') as Products
from _orders o
الذي يخرج ما أريده ، ومع ذلك فهو بطيء للغاية بالنسبة لكميات كبيرة من البيانات. أحد الجداول للأطفال هو أكثر من مليوني صف ، مما دفع وقت المعالجة إلى 4 ساعات تقريبًا.
orderid Products
----------- -----------------------
1 100 158 234
2 125
3 101 105 212 250
المحلول
بحكم التعريف ، سيتعين على المحور التجميع بطريقة ما ، لأنه يمكنك الحصول على صفوف متعددة مع نفس أعمدة المفاتيح المحورية. إذا لم يكن لديك صفوف متعددة ، فلا بأس بذلك - لكن لا تزال بحاجة إلى اختيار مشغل إجمالي (Min ، Max ، Sum).
لكن ال FOR XML PATH
يعد البناء أفضل للقيم المتعددة للصفوف إلى عملية "محور" عمود أحادي السلسلة.
لست متأكدًا من سبب عدم أداءك جيدًا. ما هي الفهارس التي لديك على الجداول؟ كيف تبدو خطة التنفيذ الخاصة بك؟