Я ищу наиболее эффективный способ превратить строки в столбцы. У меня есть требование для вывода содержимого БД (не фактическая схема ниже, но концепция похожа) как в фиксированной ширине, так и в формате с разделителями. Приведенный ниже запрос FOR 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)
с использованием FOR 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