2009-04-29 13 views
8

Mam tabelę z kolumnami sales(int), month(int). Chcę odzyskać sumę sprzedaży odpowiadającą co miesiąc. Potrzebuję ouput w formie 12 kolumn odpowiadających każdemu miesiącowi, w którym będzie jeden rekord zawierający sprzedaż dla każdej kolumny (miesiąc).Serwer SQL: konwersja wierszy do kolumn

Odpowiedz

10

Należy przyjrzeć PIVOT do przełączania wiersze z kolumnami. Zapobiega to instrukcji select dla każdego miesiąca. Coś takiego:

DECLARE @salesTable TABLE 
(
    [month] INT, 
    sales INT 
) 

-- Note that I use SQL Server 2008 INSERT syntax here for inserting 
-- multiple rows in one statement! 
INSERT INTO @salesTable 
VALUES (0, 2) ,(0, 2) ,(1, 2) ,(1, 2) ,(2, 2) 
     ,(3, 2) ,(3, 2) ,(4, 2) ,(4, 2) ,(5, 2) 
     ,(6, 2) ,(6, 2) ,(7, 2) ,(8, 2) ,(8, 2) 
     ,(9, 2) ,(10, 2) ,(10, 2) ,(11, 2) ,(11, 2) 

SELECT [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11] 
FROM 
(
    SELECT [month], sales 
    FROM @salesTable 
) AS SourceTable 
PIVOT 
(
    SUM(sales) 
    FOR [month] IN ([0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11]) 
) AS PivotTable 
+0

powinieneś pokazać regularną składnię INSERT przed rokiem 2008 –

+0

Masz prawdopodobnie rację, chociaż pytanie nie wspomniało o wersji SQL Server. Zaktualizowano moją odpowiedź, aby powiadomić czytelnika o różnicy składni. –

+0

@sahil garg: Czy to działa? –

2

Nie całkiem ... ale to działa dobrze

SELECT 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 1) [Sales1], 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 2) [Sales2], 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 3) [Sales3], 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 4) [Sales4], 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 5) [Sales5], 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 6) [Sales6], 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 7) [Sales7], 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 8) [Sales8], 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 9) [Sales9], 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 10) [Sales10], 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 11) [Sales11], 
    (SELECT SUM(Sales) FROM SalesTable WHERE [Month] = 12) [Sales12] 
1

Możesz to zrobić z OLAP. Here to kolejny link do dokumentacji MSDN na ten temat.

Dzięki OLAP możesz stworzyć sześcian z posiadanymi informacjami i odpowiednim układem.

Jeśli nie chcesz tego robić, będziesz musiał utworzyć tabele podsumowań z .NET, Java, TransacSQL lub preferowanym językiem do manipulowania danymi SQLServer.

2

Oto alternatywny sposób zapisu przestawnego, który daje trochę większą kontrolę (szczególnie nad nazwami kolumn). Jest także nieco łatwiej generować dynamiczny SQL dla.

Jest podobny do odpowiedzi Robin, ale ma tę zaletę, że tylko uderzanie w stół raz:

select 
    Sales1 = sum(case when Month = 1 then Sales end) 
, Sales2 = sum(case when Month = 2 then Sales end) 
, Sales3 = sum(case when Month = 3 then Sales end) 
-- etc.. 
from SalesTable; 

zrobiłem jakieś dochodzenie, a wydaje się, że nowy operator obrotu jest tylko cukier składni tego typu zapytania . Plany kwerend wyglądają identycznie.

Co ciekawe, operator unpivot wydaje się być również cukrem składniowym. Na przykład:

Jeśli masz stolik jak:

Create Table Sales (JanSales int, FebSales int, MarchSales int...) 

Można napisać:

select unpivoted.monthName, unpivoted.sales 
from Sales s 
outer apply (
    select 'Jan', JanSales union all 
    select 'Feb', FebSales union all 
    select 'March', MarchSales 
) unpivoted(monthName, sales); 

i uzyskać dane nieprzestawne ...

0

Aby łatwo transpozycji kolumn na wiersze ze swoimi nazwami powinieneś używać XML. W moim blogu opisałem to na przykładzie: Link