2008-12-07 12 views
8

J'ai un problème simple lors de l'interrogation de la base de données SQL Server 2005. J'ai des tables appelées Customer et Products (1-> M). Un client a plus de 2 produits. Au lieu de la production commeComment transformer des lignes en colonnes

CustomerName, ProductName ...

J'aime la sortie comme

CustomerName, Product1Name, Product2Name ...

Quelqu'un pourrait me aider?

Merci!

Répondre

10

Comme d'autres l'ont dit, vous pouvez utiliser les opérateurs PIVOT et UNPIVOT. Malheureusement, l'un des problèmes avec PIVOT et UNPIVOT est que vous devez connaître les valeurs sur lesquelles vous allez pivoter à l'avance ou utiliser le SQL dynamique.

Dans votre cas, il semble que vous ayez besoin d'utiliser du SQL dynamique. Pour que cela fonctionne bien, vous devrez faire une liste des produits utilisés dans votre requête. Si vous utilisez la base de données AdventureWorks, votre code ressemblera à ceci:

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; 

Maintenant que vous avez vos colonnes, vous pouvez tirer tout ce dont vous avez besoin pivoter avec une requête dynamique:

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 

Bien sûr, si vous devez vous assurer que vous obtenez des valeurs décentes, vous devrez dupliquer la logique que vous utilisez pour construire @columns et créer une variable @coalesceColumns qui contiendra le code à COALESCE (col_name, 0) si vous avez besoin ce genre de chose dans votre requête.

1

en sql2005, il existe des fonctions appelées "PIVOT" et "UNPIVOT" qui peuvent être utilisées pour transformer entre les lignes et les colonnes.

Espérons que cela pourrait vous aider.

1

Comme d'autres l'ont mentionné, SQL 2005 a la fonction PIVOT qui est probablement la meilleure pour un usage général. Dans certains cas, cependant, vous pouvez simplement faire quelque chose comme ça.

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 
Questions connexes