SQL-сервер: преобразование строк в столбцы

У меня есть таблица со столбцами sales(int), month(int). Я хочу получить сумму продаж, соответствующую каждому месяцу. Мне нужен вывод в виде 12 столбцов, соответствующих каждому месяцу, в котором будет одна запись, содержащая продажи для каждого столбца (месяца).


person Maddy.Shik    schedule 29.04.2009    source источник


Ответы (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
person Ronald Wildenberg    schedule 29.04.2009
comment
Вероятно, вы правы, хотя в вопросе не упоминалась версия SQL Server. Обновлен мой ответ, чтобы уведомить читателя о синтаксической разнице. - person Ronald Wildenberg; 18.05.2009

Некрасиво... но это работает хорошо

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]
person Robin Day    schedule 29.04.2009

Вот альтернативный способ написания сводки, который дает вам немного больше контроля (особенно над именами столбцов). Также немного проще генерировать динамический 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 );

И получить несводные данные...

person John Gibb    schedule 01.05.2009

Вы можете сделать это с помощью OLAP. Вот еще одна ссылка на документацию MSDN по этой теме .

С помощью OLAP вы можете создать куб с имеющейся у вас информацией и с нужным вам макетом.

Если вы не хотите идти по этому пути, вам придется создавать сводные таблицы с помощью .NET, Java, TransacSQL или предпочитаемого вами языка для управления данными SQLServer.

person Pablo Santa Cruz    schedule 29.04.2009

Чтобы легко транспонировать столбцы в строки с их именами, вы должны использовать XML. В моем блоге я описал это на примере: Ссылка

person Dalex    schedule 08.04.2011