如何将 SQL 服务器结果集行转换为具有变量列和行的列

How to convert SQL server result set Rows to Column with variable Comumn and rows

我正在将这些数据从内部从各种来源收集的一个视图中获取,我想以规范化的方式格式化这些数据,以便在 SSRS 中轻松用于图表目的。

原始数据

ServerName  TimeStamp               CPU_PCT_Utilization
Server_01   2015-04-16 16:23:04.000 2.781995773
Server_01   2015-04-16 16:28:04.000 2.804701567
Server_01   2015-04-16 17:23:04.000 2.804701567
Server_02   2015-04-21 04:33:02.000 1.094034672
Server_02   2015-04-20 17:28:02.000 1.34284699
Server_02   2015-04-20 17:33:02.000 3.027540922
Server_02   2015-04-20 13:28:03.000 0.860414088
Server_02   2015-04-20 13:33:03.000 0.785780609
Server_02   2015-04-20 18:28:02.000 3.027540922
Server_03   2015-04-21 07:04:57.000 1.316953659
Server_03   2015-04-21 07:09:57.000 1.483076811
Server _??  …   .
Server _??  ..  .
Server _??  .   .
Server _??  .   .

需要输出

TimeStamp   Server_01   Server_02   Server_03   Server _??  Server _??
2015-04-16 16:23:04.000 2.781995773 NULL    NULL    NULL    .
2015-04-16 16:28:04.000 2.804701567 NULL    NULL    .   …
2015-04-16 17:23:04.000 2.804701567 NULL    NULL    …   .
2015-04-21 04:33:02.000 NULL    1.094034672 NULL    .   .
2015-04-20 17:28:02.000 NULL    1.34284699  NULL    .   …
2015-04-20 17:33:02.000 NULL    3.027540922 NULL    …   NULL
2015-04-20 13:28:03.000 NULL    0.860414088 NULL    .   NULL
2015-04-20 13:33:03.000 NULL    0.785780609 NULL    .   NULL
2015-04-20 18:28:02.000 NULL    3.027540922 NULL    …   NULL
2015-04-21 07:04:57.000 NULL    NULL    1.316953659 .   ..
2015-04-21 07:09:57.000 NULL    NULL    1.483076811 .   .
…   .   …   .   NULL    …
..  .   ..  .   .   …
.   …   NULL    …   .   .
.   .   .   .   …   .

我试过使用 pivot 但没有用,如果有人能为此编写查询就太好了,这里的行和列都是动态的。

Simple way to transpose columns and rows in Sql? 上发布了类似的解决方案,但具有固定值。

要旋转到列的值不是常量,您必须使用 动态 SQL,您需要 dynamic sql 来构建以下语句:

case ServerName
   when 'Server_n' then CPU_PCT_Utilization
   else null 
end as Server_n

为了构建上面的语句,你可以 select distinct 上面模板中的服务器名称到一个变量中:

declare @CaseStmnt varchar(max)=''
select @CaseStmnt=',case ServerName
when '''+s+''' then CPU_PCT_Utilization
else null 
end as '+s+@CaseStmnt
from (select distinct ServerName s from pvtTbl) q  

下面是a demo of what I said:

MS SQL 服务器架构设置:

create table pvtTbl(ServerName varchar(10), dt datetime,CPU_PCT_Utilization float);
go
insert into pvtTbl values
('Server_01',   '2015-04-16 16:23:04.000', 2.781995773),
('Server_01',   '2015-04-16 16:28:04.000', 2.804701567),
('Server_01',   '2015-04-16 17:23:04.000', 2.804701567),
('Server_02',   '2015-04-21 04:33:02.000', 1.094034672),
('Server_02',   '2015-04-20 17:28:02.000', 1.34284699),
('Server_02',   '2015-04-20 17:33:02.000', 3.027540922),
('Server_02',   '2015-04-20 13:28:03.000', 0.860414088),
('Server_02',   '2015-04-20 13:33:03.000', 0.785780609),
('Server_02',   '2015-04-20 18:28:02.000', 3.027540922),
('Server_03',   '2015-04-21 07:04:57.000', 1.316953659),
('Server_03',   '2015-04-21 07:09:57.000', 1.483076811);

查询:

declare @CaseStmnt varchar(max)=''
select @CaseStmnt=@CaseStmnt+', case ServerName
when '''+s+''' then CPU_PCT_Utilization
else null 
end as '+s
from (select distinct ServerName s from pvtTbl) q 
exec('select dt '+@CaseStmnt+' from pvtTbl')

结果:

|                      dt |   Server_01 |   Server_02 |   Server_03 |
|-------------------------|-------------|-------------|-------------|
| April, 16 2015 16:23:04 | 2.781995773 |      (null) |      (null) |
| April, 16 2015 16:28:04 | 2.804701567 |      (null) |      (null) |
| April, 16 2015 17:23:04 | 2.804701567 |      (null) |      (null) |
| April, 21 2015 04:33:02 |      (null) | 1.094034672 |      (null) |
| April, 20 2015 17:28:02 |      (null) |  1.34284699 |      (null) |
| April, 20 2015 17:33:02 |      (null) | 3.027540922 |      (null) |
| April, 20 2015 13:28:03 |      (null) | 0.860414088 |      (null) |
| April, 20 2015 13:33:03 |      (null) | 0.785780609 |      (null) |
| April, 20 2015 18:28:02 |      (null) | 3.027540922 |      (null) |
| April, 21 2015 07:04:57 |      (null) |      (null) | 1.316953659 |
| April, 21 2015 07:09:57 |      (null) |      (null) | 1.483076811 |

您可以创建一个变量 @cols 并使用带有 XML 路径的 STUFF() 函数来构建 serverName 的动态列表以传入数据透视列表运算符,如下所示:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.ServerName)  
            FROM pvtTbl c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT dt, ' + @cols + ' from 
            (
                select serverName,dt,CPU_PCT_Utilization
                from pvtTbl
           ) x
            pivot 
            (
                 max(CPU_PCT_Utilization)
                for ServerName in (' + @cols + ')
            ) p '


execute(@query)

请参考下面的SQLFiddle解决方案:

SQL Fiddle Dynamic Pivot Example