У меня есть таблица со столбцами sales(int)
, month(int)
. Я хочу получить сумму продаж, соответствующую каждому месяцу. Мне нужен вывод в виде 12 столбцов, соответствующих каждому месяцу, в котором будет одна запись, содержащая продажи для каждого столбца (месяца).
SQL-сервер: преобразование строк в столбцы
Ответы (5)
Вам следует взглянуть на PIVOT для переключения строк со столбцами. Это предотвращает оператор select для каждого месяца. Что-то вроде этого:
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
Некрасиво... но это работает хорошо
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]
Вот альтернативный способ написания сводки, который дает вам немного больше контроля (особенно над именами столбцов). Также немного проще генерировать динамический SQL.
Это похоже на ответ Робина, но имеет то преимущество, что он попадает в стол только один раз:
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;
Я провел некоторое исследование, и кажется, что новый оператор поворота — это просто синтаксический сахар для этого типа запроса. В конечном итоге планы запросов выглядят одинаково.
Интересно отметить, что оператор unpivot также кажется просто синтаксическим сахаром. Например:
Если у вас есть таблица типа:
Create Table Sales ( JanSales int, FebSales int, MarchSales int...)
Ты можешь написать:
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 );
И получить несводные данные...
Вы можете сделать это с помощью OLAP. Вот еще одна ссылка на документацию MSDN по этой теме .
С помощью OLAP вы можете создать куб с имеющейся у вас информацией и с нужным вам макетом.
Если вы не хотите идти по этому пути, вам придется создавать сводные таблицы с помощью .NET, Java, TransacSQL или предпочитаемого вами языка для управления данными SQLServer.
Чтобы легко транспонировать столбцы в строки с их именами, вы должны использовать XML. В моем блоге я описал это на примере: Ссылка а>