在 SQL Server 2012 中使用 Pivot 函数将行数据更改为列

Posted

技术标签:

【中文标题】在 SQL Server 2012 中使用 Pivot 函数将行数据更改为列【英文标题】:change row data to column with out using Pivot function in SQL Server 2012 【发布时间】:2021-10-29 07:29:39 【问题描述】:

我正在尝试透视表数据

    Create table strategy(date date,[event] varchar(100),eType varchar(100))
    insert into  dbo.strategy (DATE, [event], eType) values
    ('1 Jan 2018' , 'ABZPD', 'dev'),
    ('1 Jan 2018', 'BFSPD', 'stage'),
    ('1 Jan 2018', 'BFSPD', 'pre-dep');


select * from strategy

预期输出:

DATE ABZPD BFSPD BFSZH BHXPD BHXZH BRSZH BRUPQ
2018-01-01 dev stage NULL NULL NULL NULL NULL
2018-01-01 NULL pre-dep NULL NULL NULL NULL NULL

我尝试了以下代码

SELECT * 
FROM  
(
  SELECT DATE
               ,[event]
               ,eType 
          FROM  [strategy] 
          where datename(year, DATE) = 2018 or datename(year,DATE)=2019
) AS SourceTable  
PIVOT  
(  
  MAX(eType)
          FOR event  IN ([ABZPD],[BFSPD]
,[BFSZH]
,[BHXPD]
,[BHXZH]
,[BRSZH]
,[BRUPQ] )  
) AS PivotTable;  



drop table strategy

下面是我得到的输出:

DATE ABZPD BFSPD BFSZH BHXPD BHXZH BRSZH BRUPQ
2018-01-01 dev stage NULL NULL NULL NULL NULL

【问题讨论】:

为什么dev属于第一条记录而不属于第二条记录?这就是为什么你没有得到你所期望的,因为 pivot 使用隐式聚合工作,你不能在同一日期有 2 个最大值 【参考方案1】:

您可以通过在查询中添加 ROW_NUMBER 来实现这一点,但无论如何 - 您选择 MAX(etype),因此您显示的结果是正确的...您希望通过查询实现什么?预期的结果看起来有点奇怪......但是,以 Rownumber 为例:

DECLARE @strategy TABLE(date date,[event] varchar(100),eType varchar(100))

insert into  @strategy (DATE, [event], eType) values
('1 Jan 2018' , 'ABZPD', 'dev'),
('1 Jan 2018', 'BFSPD', 'stage'),
('1 Jan 2018', 'BFSPD', 'pre-dep');


WITH cteStrategy AS(
SELECT *, ROW_NUMBER() OVER (PARTITION BY date, event ORDER BY eType) rn
  FROM @strategy
)
SELECT * 
FROM  
(
  SELECT DATE
               ,[event]
               ,eType 
               ,rn
          FROM  cteStrategy 
          where datename(year, DATE) = 2018 or datename(year,DATE)=2019
) AS SourceTable  
PIVOT  
(  
  MAX(eType)
          FOR event  IN ([ABZPD],[BFSPD]
,[BFSZH]
,[BHXPD]
,[BHXZH]
,[BRSZH]
,[BRUPQ] )  
) AS PivotTable; 

【讨论】:

【参考方案2】:

我建议将查询编写为:

select date,
       max(case when event = 'ABZPD' then eType end) as ABZPD,
       max(case when event = 'BFSPD' then eType end) as BFSPD,
       max(case when event = 'BFSZH' then eType end) as BFSZH,
       max(case when event = 'BHXPD' then eType end) as BHXPD,
       max(case when event = 'BHXZH' then eType end) as BHXZH,
       max(case when event = 'BRUPQ' then eType end) as BRUPQ
from (select s.*,
             row_number() over (partition by date order by date) as seqnum
      from strategy s
      where date >= '2018-01-01' and date < '2020-01-01'
     ) s
group by date, seqnum;

请特别注意对日期过滤方式的更改。 datename() 返回一个字符串,您正在将该字符串与一个数字进行比较。不要混合数据类型!无论如何,日期范围通常更适合字符串比较。

我更喜欢条件聚合而不是定制的pivot 功能,因为聚合更加灵活。

【讨论】:

以上是关于在 SQL Server 2012 中使用 Pivot 函数将行数据更改为列的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 2012 中计算移动平均线

在 SQL Server 2012 上使用 sql 数据库和在 SQL Server Express 2012 上使用同一个数据库是一样的吗?

如何在火花中使用 sql server 2012 jdbc jar

在 SQL Server 2012 中使用 Pivot 函数将行数据更改为列

sql server 2012 一直卡在这

如何在 SQL Server 2012 中使用 html 更改表格中特定单元格的颜色?