【问题标题】:SQL server: convert rows to columnsSQL server:将行转换为列
【发布时间】:2010-10-22 13:27:52
【问题描述】:

我有一个包含sales(int)month(int) 列的表格。我想检索每个月对应的销售额总和。我需要以与每个月对应的 12 列的形式输出,其中将有一条记录包含每个列(月)的销售额。

【问题讨论】:

    标签: sql-server tsql rows


    【解决方案1】:

    您应该查看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
    

    【讨论】:

    • 您可能是对的,尽管问题没有提到 SQL Server 版本。更新了我的答案以通知读者语法差异。
    【解决方案2】:

    不漂亮……但这很好用

    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]
    

    【讨论】:

      【解决方案3】:

      这是编写枢轴的另一种方法,可让您获得更多控制权(尤其是对列名)。为其生成动态 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 );
      

      并获取未透视的数据...

      【讨论】:

        【解决方案4】:

        您可以使用OLAP 完成此操作。 Here 是有关该主题的 MSDN 文档的另一个链接。

        使用 OLAP,您可以使用您拥有的信息和您需要的布局创建一个多维数据集。

        如果您不想这样做,则必须使用 .NET、Java、TransacSQL 或您的首选语言创建汇总表来操作 SQLServer 数据。

        【讨论】:

          【解决方案5】:

          要轻松地将列转换为具有其名称的行,您应该使用 XML。在我的博客中,我通过示例进行了描述:Link

          【讨论】:

            猜你喜欢
            • 2021-02-24
            • 2013-02-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多