这是我第一次在stackoverflow上发帖。我希望我能正确地做到这一点。
我有一个SQL Server 2014表,其中包含我需要旋转到具有多列的单个记录中的“Verticle”数据。 bluefeet的回答(SQL Server 2008 Vertical data to Horizontal)几乎让我感到满意,但并不完全。我有临时表“#Columns”,其中包含可根据数据更改的列名列表,以及包含我的数据的表“Transaction”。以下是#Columns表的内容:
ColumnName SeqNum
时间1
区域2
密度3
Ref Index 4
H2SO4 5
pH 6
尿素7
AN 8
TN 9
比率10
NH3 11
SpGr 12
Cl2 13
Fe 14
总数15
评论99
以下是Transaction表中的相关数据:
TransactionId SamplePoint_Id SP_Chem_Id EntryDate Time Chem_Id Value Comment
636 18 108 7/19/2017 1219 21 1 NULL<br>
637 18 109 7/19/2017 1219 22 2 NULL<br>
638 18 110 7/19/2017 1219 28 3 NULL<br>
639 18 111 7/19/2017 1219 1 4 NULL<br>
640 18 112 7/19/2017 1219 51 693.51 NULL<br>
641 18 113 7/19/2017 1219 2 -442.68 NULL<br>
642 18 114 7/19/2017 1219 61 168.58 NULL<br>
643 18 115 7/19/2017 1219 52 -0.64 NULL<br>
644 18 116 7/19/2017 1219 4 0.1 NULL<br>
645 18 117 7/19/2017 1219 62 1.009 NULL<br>
646 18 NULL 7/19/2017 1219 54 5 NULL<br>
647 18 NULL 7/19/2017 1219 12 6 NULL<br>
648 18 NULL 7/19/2017 1219 33 7 NULL<br>
649 18 NULL 7/19/2017 1219 70 NULL 8.88889E+12<br>
650 18 NULL 7/19/2017 1219 71 NULL NULL<br>
651 18 108 7/19/2017 1220 21 2 NULL<br>
652 18 109 7/19/2017 1220 22 3 NULL<br>
653 18 110 7/19/2017 1220 28 4 NULL<br>
654 18 111 7/19/2017 1220 1 5 NULL<br>
655 18 112 7/19/2017 1220 51 1413.51 NULL<br>
656 18 113 7/19/2017 1220 2 -729.68 NULL<br>
657 18 114 7/19/2017 1220 61 404.01 NULL<br>
658 18 115 7/19/2017 1220 52 -0.52 NULL<br>
659 18 116 7/19/2017 1220 4 0.07 NULL<br>
660 18 117 7/19/2017 1220 62 2.018 NULL<br>
661 18 NULL 7/19/2017 1220 12 7 NULL<br>
662 18 NULL 7/19/2017 1220 54 8 NULL<br>
663 18 NULL 7/19/2017 1220 33 9 NULL<br>
664 18 NULL 7/19/2017 1220 70 NULL 12341234<br>
665 18 NULL 7/19/2017 1220 71 NULL NULL<br>
这是我的问题:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(ColumnName)
from #Columns
group by ColumnName, SeqNum
order by SeqNum
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = N'SELECT ' + @cols + '
from
(
SELECT
c1.ColumnName,
case when len(t.Comment) > 0 then t.Comment when c1.ColumnName = ''Time'' then t.Time else t.Value end as Value
FROM [Transaction] t
join Chemical c on t.Chem_Id = c.ChemicalId
join SamplePoint sp on t.SamplePoint_Id = sp.SampleId
join Source s on sp.Source_Id = s.SourceId
join #Columns c1
ON c.Abbrev = c1.ColumnName
where s.Name = ''' + @SourceName + ''' and t.EntryDate = ''' + @Date + '''
) x
pivot
(
max(Value)
for ColumnName in (' + @cols + ')
) p '
--print @cols
--print @query
execute sp_executesql @query;
这是我的结果:
Time Area Density Ref Index H2SO4 pH Urea AN TN Ratio NH3 SpGr Cl2 Fe Gross Comment<br>
1220 NULL 2 3 4 5 693.51 -729.68 404.01 -0.64 0.1 2.018 8 7 9 8888888888888
问题是我只从我的查询中得到一条记录,当我想要的是两条记录 - 一条用于时间= 1219,一条用于时间= 1220.我知道(或认为)问题是聚合函数MAX,它使查询返回具有“最大值”的记录。如何获得两个记录?如果没有聚合函数,我无法使用pivot函数。感谢。
答案 0 :(得分:1)
您仍然没有从PIVOTed列中排除时间。请注意,当我说从PIVOT中排除时,我并不仅仅意味着您将其从PIVOT ... IN
列表中删除,而是您还将内部查询更改为返回时间列为单独柱。这就是为什么我建议仔细阅读add noquote function in front of paste文档以了解PIVOT
函数的工作原理。
内部查询SELECT
应更改为此(Time
作为单独的列返回,而CASE
未提及它):
SELECT t.TIME, c1.ColumnName,
CASE
WHEN len(t.Comment) > 0 THEN t.Comment
ELSE t.Value
END AS Value
Pivot
部分应该成为此(无Time
列):
pivot ( max(Value) for ColumnName in ([Area], [Density], [Ref Index], [H2SO4], [pH], [Urea], [AN]], [TN], [Ratio], [NH3], [SpGr], [Cl2], [Fe], [Gross], [Comment]) ) p
从#Columns
表中删除时间。