【问题标题】:How can I transpose a sql result like in excel's pivot function?如何像 excel 的数据透视函数一样转置 sql 结果?
【发布时间】:2013-04-07 14:28:16
【问题描述】:

我在 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

我需要的看起来像这样 - 对于每个周期(行)我对每个模式(列)的聚合量感兴趣:

PeriodStart car pt  
0               19
1               24
2               24
3           4   25
4           64  27

如何通过 MSSQL 2012 中的 Pivot 函数来实现?是否可以动态获取列(模式)而不是在查询本身中定义它们?

【问题讨论】:

标签: sql sql-server pivot


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    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;
    

    【讨论】:

    • 我认为这忽略了问题的关键:是否可以动态获取列(模式)而不是在查询本身中定义它们?
    • 哎呀,我一定错过了问题的那一部分。正如您正确指出的那样,我提出的解决方案要求在查询中静态定义列。正如其他人指出的那样,解决方案是在动态构建的查询中使用 pivot 语句。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-12
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    相关资源
    最近更新 更多