我尝试编写查询,但需要一些帮助。
我有一些看起来像这样的数据:
但是,最终用户想要一个Pivot,以便数据显示如下:
我写了这段代码:
SELECT *
FROM
(
SELECT TOP 100
Log0.sn
,CONVERT(VARCHAR(50), Log0.capture_time) AS Instant
,CONVERT(VARCHAR(50),Log0.address) + '/' + Log0.[Key] AS 'Address/Key'
,Log0.average AS Command
,Log1.average AS Actual
FROM ih3_fan_speed_log_0 Log0
LEFT JOIN ih3_fan_speed_log_01 Log1 ON Log0.sn = Log1.sn AND
Log0.capture_time = Log1.capture_time AND Log0.address = Log1.address
WHERE Log0.sn = 'V300188' AND Log0.capture_time = '03/26/2017 13:05:00'
) Src
pivot
(
MAX(sn)
for Instant in ([1], [2], [3], [4])
) piv;
但是回归:
我的问题是:
1)为什么我的Pivot没有工作? 2)甚至可以用Pivot做我需要的东西吗?
感谢您的帮助。
根据请求,这是数据:
sn Instant Address/Key Command Actual
V300188 Mar 26 2017 1:05PM 1/EF-1 99.23 99.24
V300188 Mar 26 2017 1:05PM 2/EF-2 99.02 99.04
V300188 Mar 26 2017 1:05PM 3/EF-3 100 0
V300188 Mar 26 2017 1:05PM 4/EF-4 100 100
V300188 Mar 26 2017 1:05PM 41/MUA-1 74.58 74.58
V300188 Mar 26 2017 1:05PM 51/0-10VDC 74.58 74.58
以下是结果集:
Address/Key Command Actual 1 2 3 4
1/EF-1 99.23 99.24 NULL NULL NULL NULL
2/EF-2 99.02 99.04 NULL NULL NULL NULL
3/EF-3 100 0 NULL NULL NULL NULL
4/EF-4 100 100 NULL NULL NULL NULL
41/MUA-1 74.58 74.58 NULL NULL NULL NULL
51/0-10VDC 74.58 74.58 NULL NULL NULL NULL
答案 0 :(得分:3)
以下是如何利用动态交叉表来完成此类事情的方法。 Jeff Moden在这里有一篇很棒的文章解释这种技术。 http://www.sqlservercentral.com/articles/Crosstab/65048/
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something
(
sn varchar(10)
, Instant datetime
, [Address/Key] varchar(20)
, Command numeric(7,2)
, Actual numeric(7,2)
)
insert #Something
select 'V300188', 'Mar 26 2017 1:05PM', '1/EF-1', 99.23, 99.24 union all
select 'V300188', 'Mar 26 2017 1:05PM', '2/EF-2', 99.02, 99.04 union all
select 'V300188', 'Mar 26 2017 1:05PM', '3/EF-3', 100, 0 union all
select 'V300188', 'Mar 26 2017 1:05PM', '4/EF-4', 100, 100 union all
select 'V300188', 'Mar 26 2017 1:05PM', '41/MUA-1', 74.58, 74.58 union all
select 'V300188', 'Mar 26 2017 1:05PM', '51/0-10VDC', 74.58,74.58
declare @MaxCols int
declare @StaticPortion nvarchar(2000) =
'with OrderedResults as
(
select *, ROW_NUMBER() over(partition by sn order by instant) as RowNum
from #Something
)
select sn, instant';
declare @DynamicPortion nvarchar(max) = '';
declare @FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by sn, instant order by sn';
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select @DynamicPortion = @DynamicPortion +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then [Address/Key] end) as address' + CAST(N as varchar(6)) + CHAR(10) +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then Command end) as Command' + CAST(N as varchar(6)) + CHAR(10) +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then Actual end) as Actual' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <=
(
select top 1 Count(*)
from #Something
group by sn, instant
order by COUNT(*) desc
)
select @StaticPortion + @DynamicPortion + @FinalStaticPortion
declare @SqlToExecute nvarchar(max) = @StaticPortion + @DynamicPortion + @FinalStaticPortion;
exec sp_executesql @SqlToExecute
答案 1 :(得分:1)
动态数据透视的另一种选择
扭曲是最终结果中的非独特/重复列。如您所见,这是通过简单的替换(x3)解决的。
Declare @SQL varchar(max) = Stuff((Select Distinct ','+QuoteName(concat('A',ColGrp))
+','+QuoteName(concat('B',ColGrp))
+','+QuoteName(concat('C',ColGrp))
From (Select Distinct ColGrp=Row_Number() over (Partition By sn,Instant Order by [Address/Key]) From YourTable ) A
Order By 1
For XML Path('')),1,1,'')
Select @SQL = '
Select [SN],[Instant],' + replace(replace(replace(@SQL,'[A','[Address/Key]=[A'),'[C','[Actual]=[C'),'[B','[Command]=[B') + '
From (
Select [SN]
,[Instant]
,[Col] = Concat(B.Prefix,RN )
,B.Value
From (Select *,RN=Row_Number() over (Partition By sn,Instant Order by [Address/Key]) From YourTable) A
Cross Apply (values (''A'',[Address/Key])
,(''B'',cast(Command as varchar(25)))
,(''C'',cast(Actual as varchar(25)))
) B (PreFix,Value)
) A
Pivot (max([Value]) For [Col] in (' + @SQL + ') ) p'
--Print @SQL
Exec(@SQL);
<强>返回强>
编辑 - 如果它有助于可视化
生成的SQL看起来像这样
Select [SN],[Instant],[Address/Key]=[A1],[Command]=[B1],[Actual]=[C1],[Address/Key]=[A2],[Command]=[B2],[Actual]=[C2],[Address/Key]=[A3],[Command]=[B3],[Actual]=[C3],[Address/Key]=[A4],[Command]=[B4],[Actual]=[C4],[Address/Key]=[A5],[Command]=[B5],[Actual]=[C5],[Address/Key]=[A6],[Command]=[B6],[Actual]=[C6]
From (
Select [SN]
,[Instant]
,[Col] = Concat(B.Prefix,RN )
,B.Value
From (Select *,RN=Row_Number() over (Partition By sn,Instant Order by [Address/Key]) From YourTable) A
Cross Apply (values ('A',[Address/Key])
,('B',cast(Command as varchar(25)))
,('C',cast(Actual as varchar(25)))
) B (PreFix,Value)
) A
Pivot (max([Value]) For [Col] in ([A1],[B1],[C1],[A2],[B2],[C2],[A3],[B3],[C3],[A4],[B4],[C4],[A5],[B5],[C5],[A6],[B6],[C6]) ) p