【问题标题】:SQL sum by year report, looking for an elegant solutionSQL sum by year report,寻找优雅的解决方案
【发布时间】:2012-12-01 10:20:27
【问题描述】:

我有一个包含 3 列的表:ItemCode、Quantity 和 DocDate。 我想以更“优雅”的方式创建以下报告:

SELECT T0.ItemCode, 
       (SELECT SUM(QUANTITY) FROM MyTable T1 WHERE YEAR(T0.DocDate) = 2011 AND T0.ItemCode = T1.ItemCode) AS '2011',
       (SELECT SUM(QUANTITY) FROM MyTable T1 WHERE YEAR(T0.DocDate) = 2012 AND T0.ItemCode = T1.ItemCode) AS '2012'
FROM MyTable T0
GROUP BY T0.ItemCode, YEAR(T0.DocDate)

我很确定有一种更好、更有效的方法来编写它,但我想不出正确的语法。有什么想法吗?

【问题讨论】:

    标签: sql sql-server sql-server-2008 tsql pivot


    【解决方案1】:

    你可以试试这个:

    SELECT  T0.ItemCode, 
            SUM(CASE WHEN YEAR(T0.DocDate) = 2011 THEN QUANTITY ELSE 0 END) AS '2011',
            SUM(CASE WHEN YEAR(T0.DocDate) = 2012 THEN QUANTITY ELSE 0 END) AS '2012'
    FROM    MyTable T0
    GROUP BY 
            T0.ItemCode
    

    【讨论】:

      【解决方案2】:

      这种类型的数据转换称为PIVOT。您可以通过多种方式执行此操作。您可以使用PIVOT 函数,也可以使用带有CASE 语句的聚合函数:

      Static Pivot 版本:这是您将所有值硬编码到查询中的地方

      select ItemCode, [2011], [2012]
      from
      (
        SELECT ItemCode,
          QUANTITY,
          YEAR(DocDate) Year
        FROM MyTable 
      ) src
      pivot
      (
        sum(quantity)
        for year in ([2011], [2012])
      ) piv
      

      SQL Fiddle with Demo

      聚合案例:

      SELECT ItemCode, 
        SUM(CASE WHEN YEAR(DocDate) = 2011 THEN QUANTITY ELSE 0 END) AS '2011',
        SUM(CASE WHEN YEAR(DocDate) = 2012 THEN QUANTITY ELSE 0 END) AS '2012'
      FROM    MyTable 
      GROUP BY ItemCode;
      

      SQL Fiddle with Demo

      Dynamic Pivot:如果您有已知数量的 year 值要转换,前两个版本会很好用,但如果您有未知数量,则可以使用动态 sql: p>

      DECLARE @cols AS NVARCHAR(MAX),
          @query  AS NVARCHAR(MAX)
      
      select @cols = STUFF((SELECT distinct ',' + QUOTENAME(YEAR(DocDate)) 
                          from mytable
                  FOR XML PATH(''), TYPE
                  ).value('.', 'NVARCHAR(MAX)') 
              ,1,1,'')
      
      set @query = 'SELECT itemcode, ' + @cols + ' from 
                   (
                      select itemcode, quantity, year(docdate) year
                      from mytable
                  ) x
                  pivot 
                  (
                      sum(quantity)
                      for year in (' + @cols + ')
                  ) p '
      
      execute(@query)
      

      SQL Fiddle with Demo

      所有三个版本都会产生相同的结果:

      | ITEMCODE | 2011 | 2012 |
      --------------------------
      |        1 |  200 |   45 |
      |        2 |   89 |    0 |
      |        3 |    0 |    7 |
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多