2013-03-07 13 views
9

Ich habe die folgende Herausforderung. Ich muss Tabellendaten zweimal über dieselbe Spalte drehen. Hier ist ein Screenshot der Daten.Ist es möglich, mehrere Pivots mit der gleichen Pivot-Spalte mit SQL Server

A list of items with a purchasing and a selling value for each year the items were sold

Ich mag eine Zeile für jedes Item ID habe sowohl den Kaufwert und den Verkaufswert für jedes Jahr enthält. Ich habe versucht, dies zu tun, indem Sie die "Jahr" -Spalte zweimal, formatieren sie ein wenig, so dass jedes Verkaufsjahr mit einem "S" vorangestellt wird und jedes Jahr beginnt mit einem "P", und mit 2 Pivots um das 2 Jahr zu drehen Säulen. Hier ist die SQL-Abfrage (verwendet in SQL Server 2008):

SELECT [Item ID], 
     [P2000],[P2001],[P2002],[P2003], 
     [S2000],[S2001],[S2002],[S2003] 
FROM 
(

SELECT [Item ID] 
     ,'P' + [Year] AS YearOfPurchase 
     ,'S' + [Year] AS YearOfSelling 

    ,[Purchasing value] 
    ,[Selling value] 
    FROM [ItemPrices] 
) AS ALIAS 

PIVOT 
(
MIN ([Purchasing value]) FOR [YearOfPurchase] in ([P2000],[P2001],[P2002],[P2003]) 
) 
AS pvt 

PIVOT 
(
MIN ([Selling value]) FOR [YearOfSelling] in ([S2000],[S2001],[S2002],[S2003]) 
) 
AS pvt2 

Das Ergebnis ist nicht genau das, was ich gehofft hatte (siehe Bild unten):

Actual situation: Too many rows

Wie Sie sehen können, gibt sind immer noch mehr als eine Zeile für jede Artikel-ID. Gibt es eine Möglichkeit, die Anzahl der Zeilen auf genau eins pro Element zu reduzieren? So dass es ein bisschen wie der Excel-Screenshot unten aussieht?

Desired situation: One row for each item ID

Antwort

17

Mein Vorschlag wäre, sowohl die UNPIVOT als auch die PIVOT Funktionen zu verwenden, um das Ergebnis zu erhalten.

Die UNPIVOT wird die Spalten PurchasingValue und SellingValue in Zeilen umwandeln. Sobald dies erledigt ist, können Sie die Daten in Ihr Ergebnis pivotieren. sein

wird der Code:

select * 
from 
(
    select itemid, 
    case 
     when col = 'PurchasingValue' then 'P' 
     when col = 'SellingValue' then 'S' 
    end + cast(year as varchar(4)) new_col, 
    value 
    from yourtable 
    unpivot 
    (
    value 
    for col in ([PurchasingValue], [SellingValue]) 
) unpiv 
) src 
pivot 
(
    max(value) 
    for new_col in (P2000, P2001, P2002, P2003, 
        S2000, S2001, S2002, S2003) 
) piv; 

SQL Fiddle with Demo See. Das Ergebnis ist:

| ITEMID | P2000 | P2001 | P2002 | P2003 | S2000 | S2001 | S2002 | S2003 | 
-------------------------------------------------------------------------- 
|  1 | 1000 | 1100 | 1200 | 1300 | 900 | 990 | 1080 | 1170 | 
|  2 | 500 | 550 | 600 | 650 | 450 | 495 | 540 | 585 | 

In SQL Server 2008+ Sie CROSS APPLY mit VALUES zusammen mit der PIVOT Funktion verwenden können:

select * 
from 
(
    select itemid, 
    col+cast(year as varchar(4)) new_col, 
    value 
    from yourtable 
    cross apply 
    (
    VALUES 
     (PurchasingValue, 'P'), 
     (SellingValue, 'S') 
    ) x (value, col) 
) src 
pivot 
(
    max(value) 
    for new_col in (P2000, P2001, P2002, P2003, 
        S2000, S2001, S2002, S2003) 
) piv 

SQL Fiddle with Demo Siehe

+0

Danke für die Unpivot-Vorschlag. Das war mir nicht in den Sinn gekommen (und nicht sicher, ob es in Zukunft so sein würde :-)) –

+1

@RobVermeulen Ja die Unpivot-Funktion funktioniert super. Ich habe gerade meine Antwort mit einer Version aktualisiert, die 'cross apply' verwendet. Die beiden werden das gleiche Ergebnis erhalten. – Taryn

+0

Würde "Cross Apply" schneller sein? –

3

Verwenden einer GROUP BY ItemID, mit Aggregatfunktion SUM (isnull (Wert, 0)) auf jeder der Spalten Ergebnisse.

2

Eine einfache Möglichkeit, mehrere Spalten zu schwenken, ist zu Verwenden Sie nur Aggregat (Case) -Ausdrücke.

SELECT [Item ID], 
     [P2000] = SUM(CASE WHEN [Year] = 2000 THEN [Purchasing value] END), 
     [P2001] = SUM(CASE WHEN [Year] = 2001 THEN [Purchasing value] END), 
     [P2002] = SUM(CASE WHEN [Year] = 2002 THEN [Purchasing value] END), 
     [P2003] = SUM(CASE WHEN [Year] = 2003 THEN [Purchasing value] END), 
     [S2000] = SUM(CASE WHEN [Year] = 2000 THEN [Selling value] END), 
     [S2001] = SUM(CASE WHEN [Year] = 2001 THEN [Selling value] END), 
     [S2002] = SUM(CASE WHEN [Year] = 2002 THEN [Selling value] END), 
     [S2003] = SUM(CASE WHEN [Year] = 2003 THEN [Selling value] END) 
FROM ItemPrices 
GROUP BY [Item ID] 
Verwandte Themen