2008-12-07 29 views
8

Tengo un problema simple al consultar la base de datos de SQL Server 2005. Tengo tablas llamadas Cliente y Productos (1-> M). Un cliente tiene la mayoría de los 2 productos. En lugar de salida comoCómo transformar filas en columnas

CustomerName, ProductName ...

me gusta salida como

CustomerName, Product1Name, Product2Name ...

Podría alguien ayudarme?

Gracias!

Respuesta

10

Como otros han dicho, puede utilizar el pivote y los operadores UNPIVOT. Desafortunadamente, uno de los problemas tanto con PIVOT como con UNPIVOT es que necesita conocer los valores con los que pivotará de antemano o bien usar SQL dinámico.

Parece que, en su caso, va a necesitar usar SQL dinámico. Para que esto funcione bien, deberá obtener una lista de los productos que se utilizan en su consulta. Si estaba utilizando la base de datos AdventureWorks, su código se vería así:

USE AdventureWorks; 
GO 

DECLARE @columns NVARCHAR(MAX); 

SELECT x.ProductName 
INTO #products 
FROM (SELECT p.[Name] AS ProductName 
    FROM Purchasing.Vendor AS v 
    INNER JOIN Purchasing.PurchaseOrderHeader AS poh ON v.VendorID = poh.VendorID 
    INNER JOIN Purchasing.PurchaseOrderDetail AS pod ON poh.PurchaseOrderID = pod.PurchaseOrderID 
    INNER JOIN Production.Product AS p ON pod.ProductID = p.ProductID 
    GROUP BY p.[Name]) AS x; 

SELECT @columns = STUFF(
    (SELECT ', ' + QUOTENAME(ProductName, '[') AS [text()] 
     FROM #products FOR XML PATH ('') 
    ), 1, 1, ''); 

SELECT @columns; 

Ahora que tiene sus columnas, se puede tirar todo lo que necesita girar con una consulta dinámica:

DECLARE @sql NVARCHAR(MAX); 

SET @sql = 'SELECT CustomerName, ' + @columns + ' 
FROM (
    // your query goes here 
) AS source 
PIVOT (SUM(order_count) FOR product_name IN (' + @columns + ') AS p'; 

EXEC sp_executesql @sql 

Por supuesto, si necesita asegurarse de obtener valores decentes, es posible que deba duplicar la lógica que está utilizando para compilar @columns y crear una variable @coalesceColumns que contenga el código en COALESCE (col_name, 0) si necesita ese tipo de cosas en tu consulta.

1

en sql2005, hay funciones llamadas "PIVOT" y "UNPIVOT" que se pueden utilizar para transformar entre filas y columnas.

Espero que pueda ayudarlo.

1

Como han mencionado otros, SQL 2005 tiene la función PIVOT, que es probablemente la mejor para uso general. En algunos casos, sin embargo, simplemente puede hacer algo como esto.

Select 
Customer, 
Sum(Case When Product = 'Foo' Then 1 Else 0 End) Foo_Count, 
Sum(Case When Product = 'Bar' Then 1 Else 0 End) Bar_Count 
From Customers_Products 
Group By Customer