【问题标题】:T-SQL Pivot with multiple aggregates on the same column同一列上具有多个聚合的 T-SQL Pivot
【发布时间】:2013-08-11 20:04:36
【问题描述】:

这似乎应该是一个常见的需求,但我没有看到如何使用 T-SQL PIVOT 函数来做到这一点。具体来说,我想通过 Pivot 列值计算列的 AVG 和 STDEV。数据看起来像这样(很多数据被省略了,但这很重要):

--------------------------------------------------------------------------
ID           Year     PersonID     Score 
--------------------------------------------------------------------------
106          2001        1          20
107          2002        1          30       
108          2003        1          40       
109          2004        1          50     
106          2002        2          20
107          2003        2          50       
108          2004        2          30       
109          2005        2          10   
--------------------------------------------------------------------------

我想看看下面的输出

--------------------------------------------------------------------------
NonPivotCol1 NonPivotCol2  2001_Mean   2001_Avg  2002_Mean  2002_Avg  Etc 
--------------------------------------------------------------------------
Some Value   Some Value       32          5.2       28          3.1 
Etc. 
--------------------------------------------------------------------------

我需要恢复到旧的 CASE 语句逻辑吗?

谢谢!

【问题讨论】:

标签: sql-server tsql


【解决方案1】:

是的。

只需使用旧样式的CASE 语法。

SELECT AVG(CASE WHEN Year = 2001 THEN Score END) AS 2001_Avg,
       STDEV(CASE WHEN Year = 2001 THEN Score END) AS 2001_StDev /*...*/

PIVOT 无论如何只是(不太通用的)语法糖。

Oracle supports multiple aggregatesPIVOT 中,但 TSQL 没有。

【讨论】:

    【解决方案2】:

    用例语句。无论如何,您必须指定所有列,我会说这种情况比枢轴更有用

    select
      avg(case when [Year] = 2001 then [Score] else null end) as [2001_Avg],
      avg(case when [Year] = 2002 then [Score] else null end) as [2002_Avg]
    from Table1
    

    【讨论】:

      【解决方案3】:

      您必须制作两个 PIVOT 并加入它们

      WITH MinPivot AS
      (
        SELECT 
               [2001] AS [2001_MEAN], 
               [2002] AS [2002_MEAN], 
               [2003] AS [2003_MEAN], 
               [2004] AS [2004_MEAN], 
               [2005] AS [2005_MEAN]
        FROM
        (
          SELECT Year,Score
          FROM Table1
        ) As S
        PIVOT
        (
           STDEV(Score)
           FOR Year in([2001],[2002],[2003],[2004],[2005])
        )
        AS pvt
      ),
      AvgPivot AS
      (
        SELECT 
               [2001] AS [2001_AVG],
               [2002] AS [2002_AVG],
               [2003] AS [2003_AVG], 
               [2004] AS [2004_AVG], 
               [2005] AS [2005_AVG] 
        FROM
        (
          SELECT Year,Score
          FROM Table1
        ) As S
        PIVOT
        (
           AVG(Score)
           FOR Year in([2001],[2002],[2003],[2004],[2005])
        )
        AS pvt
      )
      
      SELECT *
      FROM MinPivot M
      CROSS JOIN AvgPivot A
      

      看看this fiddle example

      【讨论】:

      • 这比只使用CASE 效率要低得多,因为您执行了两次分组和聚合(以及添加额外的联接)
      • 无论如何都是一种选择。
      猜你喜欢
      • 2019-02-27
      • 2018-06-28
      • 2010-11-17
      • 1970-01-01
      • 2014-11-27
      • 1970-01-01
      • 1970-01-01
      • 2011-03-15
      • 1970-01-01
      相关资源
      最近更新 更多