2009-04-29 17 views
8

Tengo una tabla con columnas sales(int), month(int). Quiero recuperar la suma de las ventas correspondientes a cada mes. Necesito una salida en forma de 12 columnas correspondientes a cada mes en el que habrá un solo registro que contenga las ventas de cada columna (mes).Servidor SQL: convertir filas en columnas

Respuesta

10

Usted debe echar un vistazo a PIVOT para cambiar filas con columnas. Esto evita una declaración de selección para cada mes. Algo como esto:

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

debe mostrar la sintaxis regular de INSERT previa a 2008 –

+0

Probablemente tenga razón, aunque la pregunta no mencionó una versión de SQL Server. Actualicé mi respuesta para notificar al lector de la diferencia de sintaxis. –

+0

@sahil garg: ¿Lo hiciste funcionar? –

2

No es bonita ... pero esto funciona bien

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

Puedes hacerlo con OLAP. Here es otro enlace a la documentación de MSDN sobre el tema.

Con OLAP, puede crear un cubo con la información que tiene, con el diseño que necesita.

Si no desea seguir así, deberá crear tablas de resumen con .NET, Java, TransacSQL o su idioma preferido para manipular los datos de SQLServer.

2

Aquí hay una manera alternativa de escribir el pivote que le da un poco más de control (especialmente sobre los nombres de las columnas). También es un poco más fácil generar SQL dinámico para.

Es similar a la respuesta de Robin, pero tiene la ventaja de tan sólo golpear la mesa una vez:

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; 

hice un poco de investigación, y parece que el nuevo operador de pivote es simplemente azúcar sintaxis para este tipo de consulta . Los planes de consulta terminan pareciendo idénticos.

Como un aspecto interesante, el operador unpivot parece ser simplemente sintaxis de azúcar. Por ejemplo:

Si tiene una tabla como:

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

puede escribir:

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); 

y obtener los datos no girados ...

0

transponer fácilmente columnas en filas con sus nombres debe usar XML. En mi blog me describieron esto con un ejemplo: Link

Cuestiones relacionadas