Pregunta

Busco la manera mas potente para convertir filas en columnas. Tengo un requisito para dar salida a los contenidos de la base de datos (esquema no real por debajo, pero el concepto es similar) tanto en anchura fija y formatos delimitados. El siguiente consulta FOR XML PATH me da el resultado que quiero, pero cuando se trata de que no sea pequeñas cantidades de datos nada, puede tomar un tiempo.

 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

He mirado en el pivote pero la mayoría de los ejemplos que hemos encontrado son la agregación de información. Sólo quiero combinar las filas secundarias y virar hacia ellos el padre.

También se debe señalar que no necesito para hacer frente a los nombres de columna, ya sea desde la salida de las filas secundarias o bien será una anchura fija de cuerda o una cadena delimitada.

Por ejemplo, teniendo en cuenta las siguientes tablas:

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

para un pedido que necesito de salida:

orderid     Products
----------- -----------------------
1             100  158  234
2             125
3             101  105  212  250

o

orderid     Products
----------- -----------------------
1           100|158|234
2           125
3           101|105|212|250

Los pensamientos o sugerencias? Estoy utilizando SQL Server 2k5.

Ejemplo de configuración:

   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)

utilizando para la trayectoria 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

que da salida a lo que yo quiero, sin embargo, es muy lento para grandes cantidades de datos. Una de las tablas hijo tiene más de 2 millones de filas, empujando el tiempo de procesamiento a ~ 4 horas.

orderid     Products
----------- -----------------------
1             100  158  234
2             125
3             101  105  212  250
¿Fue útil?

Solución

Por definición un pivote va a tener que agregar de alguna manera, porque se puede tener múltiples filas con las mismas columnas de clave de pivote. Si usted no tiene varias filas, está bien -. Pero todavía se tiene que elegir un operador agregada (MIN, MAX, SUM)

Pero el constructo FOR XML PATH es mejor para las múltiples hileras de valores a single-string-columna "pivote" operación.

No estoy seguro de por qué no el suyo es un buen rendimiento. ¿Qué índices tiene usted sobre las tablas? Lo que hace su mirada plan de ejecución como?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top