T-SQL Самый эффективный ряд к столбцу? CrosStab для XML Path, Pivot
-
26-09-2019 - |
Вопрос
Я ищу самый исполнительный способ повернуть ряды в колонны. У меня есть требование выводить содержимое БД (не фактическую схему ниже, но концепция похожа) как в фиксированной ширине, так и в форматах с разделителями. Ниже приведен к запросу Path 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
Я посмотрел на пивот, но большинство примеров, которые я нашел, - это агрегационная информация. Я просто хочу объединить дочерние ряды и прикрепить их на родитель.
Я также должен указать, что мне не нужно иметь дело с именами столбцов, поскольку вывод дочерних строк будет либо строкой фиксированной шириной или разделите строку.
Например, учитывая следующие таблицы:
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 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
который выводит то, что я хочу, однако очень медленно для больших объемов данных. Один из детских столов составляет более 2 миллионов строк, нажав время обработки до ~ 4 часа.
orderid Products
----------- -----------------------
1 100 158 234
2 125
3 101 105 212 250
Решение
По определению, поворот должен быть вообще связан, потому что вы можете иметь несколько строк с одинаковыми столбцами ключей поворота. Если у вас нет нескольких строк, это нормально - но вам все равно нужно выбрать агрегатный оператор (мин, максимум, сумму).
Но FOR XML PATH
Конструкция лучше для нескольких строк-значений к однотруконному колонку «Pivot».
Я не уверен, почему твой не выступает хорошо. Какие указатели у вас есть на столах? Как выглядит ваш план исполнения?