我在MSSQL 2012中使用以下查询:
declare @startTime int=0*3600;
declare @endTime int=30*3600;
declare @link varchar(10)='RO2566a';
declare @period int=3600;
SELECT (B.time-@startTime)/@period as periodStart, B.link, B.mode, count(*) as Volume
FROM
(
Select A.*,
case when A.vehicle='' then 'walk'
when A.line is NULL then 'car'
else 'pt' end mode
FROM
(Select E.time, E.link, E.vehicle, E.person, T.transitLineId as line, T.transitRouteId as route, T.departureId, T.time as DepartureTime
FROM (Select * From evtEnteredLink where link=@link and time between @startTime and @endTime) E
LEFT OUTER JOIN evtTransitDriverStarts T on (E.vehicle=T.vehicleId)
) A
where A.time between @startTime and @endTime
)B
group by B.link, B.mode, (B.time-@startTime)/@period
结果如下:
periodStart mode Volume
0 pt 19
1 pt 24
2 pt 24
3 car 4
3 pt 25
4 car 64
4 pt 27
我需要的是这样的 - foreach period(rows)我对每种模式的聚合体积(列)感兴趣:
PeriodStart car pt
0 19
1 24
2 24
3 4 25
4 64 27
如何通过MSSQL 2012中的Pivot功能实现这一目标?是否可以动态获取列(模式)而不是在查询本身中定义它们?
答案 0 :(得分:2)
<强> Converted from here 强>
create table temp
(
periodstart int,
mode varchar(3),
volume int
)
insert into temp values (0,'pt',19);
insert into temp values (1,'pt',24);
insert into temp values (2,'pt',24);
insert into temp values (3,'car',4);
insert into temp values (3,'pt',25);
insert into temp values (4,'car',64);
insert into temp values (4,'pt',27);
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.mode)
FROM temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT periodstart, ' + @cols + ' from
(
select periodstart
, volume
, mode
from temp
) x
pivot
(
max(volume)
for mode in (' + @cols + ')
) p '
execute(@query)
drop table temp
答案 1 :(得分:1)
T-SQL关键字pivot
应该可以满足您的需求。查看http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx(此文档适用于2008 R2,但它在SQL Server 2012中的工作方式相同)。
我还没有测试过,但基本上,这个查询应该可以解决问题:
SELECT PeriodStart, [car], [pt]
FROM
(
SELECT ... -- Insert the entire SELECT statement from your question here.
) p
PIVOT
(
SUM(Volume) -- Or MAX(), COUNT(), or whichever aggregate function suits your need.
FOR Mode IN ( [car], [pt] )
) AS pvt
ORDER BY pvt.PeriodStart;