为什么在SQL Server中转动文本列时使用Max函数?

时间:2018-01-03 13:17:30

标签: sql sql-server tsql pivot

我刚学会了如何在SQL Server中进行透视。我想知道为什么在我们想要转动文本列时使用max函数?这背后的逻辑是什么?我理解它是CountSum等(因为你对相应的行和列进行求和)但我不理解在有文本列时使用max的逻辑?

例如,我的代码是:

SELECT * 
  FROM ( SELECT DATE
               ,SITA
               ,EVENT 
          FROM  [UKRMC].[dbo].[strategy] 
          where datename(year, DATE) = 2018 or datename(year,DATE)=2019
        ) strategy
  PIVOT ( max(EVENT)
          FOR SITA IN ([ABZPD],[BFSPD]
,[BFSZH]
,[BHXPD]
,[BHXZH]
,[BRSZH]
,[BRUPQ] ) piv

2 个答案:

答案 0 :(得分:2)

使用PIVOT命令时必须指定聚合函数,因为透视操作的第一步是对FOR子句中指定的列的分组操作,该操作减少了结果的行数表。

聚合函数用于管理输出表中所需的其他列的值。

来自Technet文档:

  

PIVOT通过转动唯一值来旋转表值表达式   从表达式中的一列到输出中的多个列,   并且执行任何剩余所需的聚合   最终输出中需要的列值

以下是来自同一篇Technet文章的PIVOT命令语法:

SELECT <non-pivoted column>,  
    [first pivoted column] AS <column name>,  
    [second pivoted column] AS <column name>,  
    ...  
    [last pivoted column] AS <column name>  
FROM  
    (<SELECT query that produces the data>)   
    AS <alias for the source query>  
PIVOT  
(  
    <aggregation function>(<column being aggregated>)  
FOR   
[<column that contains the values that will become column headers>]   
    IN ( [first pivoted column], [second pivoted column],  
    ... [last pivoted column])  
) AS <alias for the pivot table>  
<optional ORDER BY clause>;  

请注意,在PIVOT子句之后,您必须指定聚合函数:

...
<aggregation function>(<column being aggregated>)
...

有关此主题的其他见解,另请参阅this Microsoft Press文章。

答案 1 :(得分:2)

因为在您的示例中,您已选择EVENT作为PIVOT交叉点中显示的值(即,您已在EVENT子句中指定PIVOT ,必须使用permissible aggregate functions之一指定值,因为当您按照其余列进行分组时,您在枢轴中选择的每个列值可能有多行(即DATE在您的列中)情况)。

在Sql Server [1] 中,MAX()MIN()通常在旋转非数字列时使用,因为它能够显示其中一个原始的列的值。

任何非聚合和非旋转列都将保持原样,并将用于形成数据透视所基于的组(在您的情况下,列DATE不在列中聚合或列枢轴,因此它将形成行组)

考虑您的透视表包含与谓词匹配的多行的情况,例如:

INSERT INTO strategy (DATE, SITA, EVENT) VALUES
('1 Jan 2018', 'ABZPD', 'Event1'),
('1 Jan 2018', 'BFSPD', 'Event2'),
('1 Jan 2018', 'BFSPD', 'Event3');

在Pivot之后:

DATE                    ABZPD   BFSPD
2018-01-01T00:00:00Z    Event1  Event3

即。在数据透视期间,BFSPDEvent2的{​​{1}}行需要以某种方式投射到单个单元格中 - 因此需要聚合。即使已知只有one value(在上例中SITA Event3的{​​{1}}值就是这种情况),仍然需要此聚合。

由于Event1有两个事件,您需要以某种方式解决如何将值投影到单个单元格值中的问题。在VARCHAR列上使用ABZPD可以解析最大的&#39;值(BFSPD)如果多行投影到相同的结果枢轴&#39;单元格&#39; - SqlFiddle example here

您可以选择使用MAX向您显示每行/枢轴交叉点的事件数量 - Fiddle

您可以使用Event3切换COUNT(Event)上的聚合 - EVENT DATE中使用EVENT

* 1 AVGSTDEV等聚合显然不适用于字符串。其他RDBMS有额外的聚合,如column grouping,它将任意取第一个值,或FIRST,它可以将字符串值与分隔符一起折叠。并且GROUP_CONCAT / LIST_AGG允许您创建自己的聚合函数!但遗憾的是,在SqlServer中没有这个,因此MIN()  / MAX()现在。