在 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 数据库和在 SQL Server Express 2012 上使用同一个数据库是一样的吗?
如何在火花中使用 sql server 2012 jdbc jar