t-sql наиболее эффективный ряд к столбцу? кросс-таблица для XML-пути, сводная - PullRequest
1 голос
/ 12 апреля 2010

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

1 Ответ

0 голосов
/ 13 апреля 2010

По определению PIVOT собирается ДОЛЖЕН объединяться, так как вы можете иметь несколько строк с одинаковыми столбцами сводных ключей. Если у вас нет нескольких строк, это нормально, но вам все равно нужно выбрать оператор агрегирования (MIN, MAX, SUM).

Но конструкция FOR XML PATH лучше подходит для операции "pivot" со столбцами из нескольких строк.

Я не уверен, почему у тебя дела идут плохо. Какие индексы у вас есть на столах? Как выглядит ваш план выполнения?

...