没有聚合的 sql server 中的 UNPIVOT
Posted
技术标签:
【中文标题】没有聚合的 sql server 中的 UNPIVOT【英文标题】:UNPIVOT in sql server without Aggregate 【发布时间】:2016-07-21 09:49:41 【问题描述】:我有一个Table
,如下所示。
OfficeID SunFrom SunTo MonFrom MonTo TueFrom TueTo WedFrom WedTo ThuFrom ThuTo FriFrom FriTo SatFrom SatTo
51834 12 17 8 22 8 22 8 22 8 22 9 21 8 19
我需要将此表的列转换为行
预期输出:
Officeid Day Daystart DayEnd
51834 Sunday 12 17
51834 Monday 8 22
51834 Tuesday 8 22
51834 Wednesday 8 22
51834 Thursday 8 22
51834 Friday 9 21
51834 Saturday 8 19
我尝试使用UNPIVOT
,但我不确定我需要选择哪一列作为pivot column
。请帮忙....
【问题讨论】:
我认为最好的方法是运行 7 个查询,每个查询针对一周中的一天。如果这是某种常规的事情,那么您可以创建一个存储过程或使用动态查询来执行此操作。 【参考方案1】:这可以解决大部分问题。如果您需要特定的输出顺序,我建议使用将 3 个字符的日期名称映射到排序索引(以及全长名称,如果需要)的辅助表:
declare @t table (OfficeID int,SunFrom int,SunTo int,MonFrom int,MonTo int,
TueFrom int,TueTo int,WedFrom int,WedTo int,
ThuFrom int,ThuTo int,FriFrom int,FriTo int,
SatFrom int,SatTo int)
insert into @t(OfficeID,SunFrom,SunTo,MonFrom,MonTo,TueFrom,TueTo,
WedFrom,WedTo,ThuFrom,ThuTo,FriFrom,FriTo,SatFrom,SatTo) values
(51834,12,17,8,22,8,22,8,22,8,22,9,21,8,19)
select
OfficeID,Day,
MAX(CASE WHEN Endpoint='From' THEN EndpointTime END) as Daystart,
MAX(CASE WHEN Endpoint='To' THEN EndpointTime END) as DayEnd
from
@t t
unpivot
(EndpointTime for DayAndEndPoint in (SunFrom,SunTo,MonFrom,MonTo,TueFrom,TueTo,
WedFrom,WedTo,ThuFrom,ThuTo,FriFrom,FriTo,SatFrom,SatTo)) a
cross apply
(select SUBSTRING(DayAndEndpoint,1,3) as Day,SUBSTRING(DayAndEndpoint,4,4) as Endpoint) b
group by
OfficeID,Day
结果:
OfficeID Day Daystart DayEnd
----------- ---- ----------- -----------
51834 Fri 9 21
51834 Mon 8 22
51834 Sat 8 19
51834 Sun 12 17
51834 Thu 8 22
51834 Tue 8 22
51834 Wed 8 22
正如您所希望的那样,如果可能的话,最好重新设计您的数据库,使其比原始结果集更接近这个结果集 - 相同“类型”的数据应该在单个列中,并且数据应该被建模为数据,而不是嵌入到列名中。
如果输出顺序和日期名称特别重要,则扩展变体:
declare @t table (OfficeID int,SunFrom int,SunTo int,MonFrom int,MonTo int,
TueFrom int,TueTo int,WedFrom int,WedTo int,
ThuFrom int,ThuTo int,FriFrom int,FriTo int,
SatFrom int,SatTo int)
insert into @t(OfficeID,SunFrom,SunTo,MonFrom,MonTo,TueFrom,TueTo,
WedFrom,WedTo,ThuFrom,ThuTo,FriFrom,FriTo,SatFrom,SatTo) values
(51834,12,17,8,22,8,22,8,22,8,22,9,21,8,19)
declare @DayNameAndSort table (Day varchar(3) not null,ExtendedName varchar(19) not null,SortOrder int not null)
insert into @DayNameAndSort (Day,ExtendedName,SortOrder) values
('Fri','Friday', 5),
('Mon','Monday', 1),
('Sat','Saturday', 6),
('Sun','Sunday', 0),
('Thu','Thursday', 4),
('Tue','Tuesday', 2),
('Wed','Wednesday',3)
;With ReOriented as (
select
OfficeID,Day,
MAX(CASE WHEN Endpoint='From' THEN EndpointTime END) as Daystart,
MAX(CASE WHEN Endpoint='To' THEN EndpointTime END) as DayEnd
from
@t t
unpivot
(EndpointTime for DayAndEndPoint in (SunFrom,SunTo,MonFrom,MonTo,TueFrom,TueTo,
WedFrom,WedTo,ThuFrom,ThuTo,FriFrom,FriTo,SatFrom,SatTo)) a
cross apply
(select SUBSTRING(DayAndEndpoint,1,3) as Day,SUBSTRING(DayAndEndpoint,4,4) as Endpoint) b
group by
OfficeID,Day
)
select
OfficeID,ExtendedName,Daystart,DayEnd
from
ReOriented r
inner join
@DayNameAndSort s
on
r.Day = s.Day
order by s.SortOrder
【讨论】:
感谢 damien..但是可以返回 day Id 而不是 dayname 吗?比如 1 代表太阳,2 代表星期一? @bmsqldev - 你应该能够调整我的第二个版本,它使用一个辅助表来引入有关日子的额外信息。以上是关于没有聚合的 sql server 中的 UNPIVOT的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server报错:选择列表中的列无效,因为该列没有包含在聚合函数或 GROUP BY 子句中