2008-12-07 16 views
8

Mam prosty problem podczas wysyłania zapytań do bazy danych SQL Server 2005. Mam tabele o nazwie Klient i produkty (1-> M). Jeden klient ma maksymalnie 2 produkty. Zamiast wyjścia jakJak przekształcać wiersze w kolumny

CustomerName, NazwaProduktu ...

Lubię wyjścia jak

CustomerName, Product1Name, Product2Name ...

Czy ktoś może mi pomóc?

Dzięki!

Odpowiedz

10

Jak mówili inni, można użyć obrotowe i operatorów UNPIVOT. Niestety, jednym z problemów zarówno z PIVOT jak i UNPIVOT jest to, że musisz znać wartości, z którymi będziesz się obracał wcześniej lub używał dynamicznego SQL.

Wygląda na to, że w twoim przypadku będziesz musiał użyć dynamicznego SQL. Aby to działało dobrze, musisz pobrać listę produktów używanych w zapytaniu. Jeśli korzystasz z bazy danych AdventureWorks, Twój kod będzie wyglądać następująco:

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; 

Teraz masz swoje kolumny, można wyciągnąć wszystko co trzeba obracać na z dynamicznym kwerendy:

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 

Oczywiście, jeśli chcesz mieć pewność, że uzyskasz przyzwoite wartości, być może będziesz musiał skopiować logikę, której używasz do budowania kolumn @ i utworzyć zmienną @coalesceColumns, która będzie przechowywać kod do COALESCE (col_name, 0), jeśli potrzebujesz tego rodzaju rzeczy w twoim zapytaniu.

1

w sql2005, istnieją funkcje o nazwie "PIVOT" i "UNPIVOT", które mogą być używane do przekształcania między wierszami i kolumnami.

Mam nadzieję, że ci pomogę.

1

Jak wspomniano, SQL 2005 ma funkcję PIVOT, która jest prawdopodobnie najlepsza do ogólnego użytku. W niektórych przypadkach można jednak po prostu zrobić coś takiego.

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 
Powiązane problemy