我有一个查询,该查询返回通道名称存在于另一个表中的数据,因此我只返回一组特定的通道。
SELECT DISTINCT
ReadingDate, SerialNumber, ChannelName, ChannelValue
FROM
[Staging].[UriData]
WHERE
ChannelName IN (SELECT ChannelName FROM [dbo].[Channels])
ORDER BY
ReadingDate DESC, ChannelName
此查询的重要性在于它只会带回存储移动数据而不是固定诊断数据的通道。
结果(摘要):
ReadingDate | SerialNumber | ChannelName | ChannelValue
2018-09-09 20:30:00 2209 m1 461
2018-09-09 20:30:00 2209 m2 0
2018-09-09 20:30:00 2209 m3 50
2018-09-09 20:30:00 2209 m4 15631
2018-09-09 20:30:00 2209 m5 1
2018-09-09 20:30:00 2209 m6 8150
2018-09-09 20:30:00 2209 m7 0
2018-09-09 20:30:00 2209 m8 2790
2018-09-09 20:30:00 2209 m9 0
2018-09-09 20:15:00 2209 m1 2452
2018-09-09 20:15:00 2209 m2 0
2018-09-09 20:15:00 2209 m3 50
2018-09-09 20:15:00 2209 m4 15629
2018-09-09 20:15:00 2209 m5 1
2018-09-09 20:15:00 2209 m6 8100
2018-09-09 20:15:00 2209 m7 0
2018-09-09 20:15:00 2209 m8 2780
然后我想将此数据透视成列,以便按日期(日期)将它们分组,然后从该日期开始计算时间。
必填输出:
DATE | SERIAL | ChannelName | 00:15 | 00:30 | ..... | 23:45
2018-09-06 2209 m1 Value Value ..... Value
2018-09-06 2209 m2 Value Value ..... Value
我一直在研究数据透视,但是我没有获得所需的格式的数据。
答案 0 :(得分:3)
您可以尝试使用 cte递归制作时间日历表,然后通过time
制作行号。
然后将动态SQL与数据透视一起使用。
这是给您的样品。
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
;WITH CTE AS (
SELECT CAST('00:00' AS TIME) startDt, CAST('23:45' AS TIME) endDt
UNION ALL
SELECT DATEADD(MINUTE, 15, startDt),endDt
FROM CTE
WHERE DATEADD(MINUTE, 15, startDt) <endDt
), TimeTable AS (
select *,ROW_NUMBER() OVER (ORDER BY startDt) rn
FROM (
SELECT startDt,endDt
FROM CTE
UNION ALL
SELECT CAST('23:45' AS TIME) startDt, CAST('23:45' AS TIME) endDt
) t1
)
select @cols = CONCAT(@cols,'MAX(CASE WHEN '''+CAST(startDt AS VARCHAR(5))+''' = CAST(ReadingDate AS TIME) THEN ChannelValue ELSE 0 end) AS ',QUOTENAME(CAST(startDt AS VARCHAR(5))),', ')
from TimeTable
WHERE startDt <= endDt
ORDER BY rn
SET @cols = left(@cols, len(@cols) - 1)
set @query = '
;WITH CTE AS ( SELECT CAST('''+ cast('00:00' as varchar(5))+''' AS TIME) startDt, CAST('''+ cast('23:45' as varchar(5))+''' AS TIME) endDt
UNION ALL
SELECT DATEADD(MINUTE, 15, startDt),endDt
FROM CTE
WHERE DATEADD(MINUTE, 15, startDt) <endDt
), TimeTable AS (
select *,ROW_NUMBER() OVER (ORDER BY startDt) rn
FROM (
SELECT startDt,endDt
FROM CTE
UNION ALL
SELECT CAST('''+ cast('23:45' as varchar(5))+''' AS TIME) startDt, CAST('''+ cast('23:45' as varchar(5))+''' AS TIME) endDt
) t1
)
SELECT CONVERT(VARCHAR(10),ReadingDate, 126),
SerialNumber,
ChannelName,
'+ @cols +'
FROM T
GROUP BY CONVERT(VARCHAR(10),ReadingDate, 126) ,SerialNumber,ChannelName
'
exec(@query)
答案 1 :(得分:2)
您还可以使用PIVOT
构造实现相同的结果,如下所示:
SELECT [Serial], [Channel], [ReadingDate], [00:15], [00:30], ....
FROM(
SELECT
SerialNumber AS [Serial],
ChannelName AS [Channel],
CAST(ReadingDate AS DATE) AS [ReadingDate],
CAST(ReadingDate AS TIME(0)) AS [ReadingTime],
ChannelValue AS [Value]
FROM [Staging].[UriData]
WHERE
ChannelName IN (SELECT ChannelName FROM Staging.ActiveChannels )
AND Processed = 0
) AS [Raw]
PIVOT
(
MAX( [Value] ) FOR [ReadingTime] IN( [00:15], [00:30], .... )
) AS pvt
ORDER BY ReadingDate DESC, Channel, [Serial]
要生成“时间”列(并使您不必手动键入),请运行以下查询:
DECLARE @cols AS NVARCHAR(MAX)
;WITH Times AS (
SELECT CAST( '00:00' AS TIME) AS [Time]
UNION ALL
SELECT DATEADD( MINUTE, 15, [Time] )
FROM Times
WHERE [Time] < CAST( '23:45' AS TIME )
)
--SELECT * FROM Times
SELECT @cols = CONCAT( @cols, QUOTENAME( CAST( [Time] AS VARCHAR( 5 ) )), ', ' )
FROM Times
SET @cols = LEFT( @cols, LEN( @cols ) - 1 )
PRINT @cols
将结果复制/粘贴到上面的“ PIVOT”查询中。