嗨,我有一张包含来自一堆传感器的历史数据的表格,我正在尝试为最接近所需时间的每个历史数据记录获取一行。例如,我想让记录最接近每一分钟。
我已将问题简化为以下内容,如果我可以解决,我可以用来通知我的一般解决方案:
按如下方式选择两个表:
CREATE TABLE [TempDataTable](
[DataIndex] [int] IDENTITY(0,2) NOT NULL,
[DataName] [varchar](40) NOT NULL,
[DataValue] [decimal](10,2) NOT NULL,
[DataTimeStamp] [datetime2](7)
)
CREATE TABLE [TempTargetTable](
[TargetIndex] [int] IDENTITY(1,2) NOT NULL,
[TargetTime] [datetime2](7)
)
对于TempTargetTable
中的每一行,获取TempDataTable
中TempDataTable.DataTimeStamp
最接近TempTargetTable.TargetTime
的行
如果我能做到这一点,我相信我可以弄清楚剩下的,但我不知道如何让这第一步开始工作。为了便于测试您的代码,我可以提供以下内容,使用一些测试数据填充两个表:
INSERT INTO [TempDataTable]
([DataName],
[DataValue],
[DataTimeStamp])
VALUES
('Sensor',0, '2017-01-01 00:00:00'),
('Sensor',0.5, '2017-01-01 00:00:17'),
('Sensor',1, '2017-01-01 00:01:03'),
('Sensor',1.5, '2017-01-01 00:01:30'),
('Sensor',1.5, '2017-01-01 00:01:38'),
('Sensor',2, '2017-01-01 00:02:01'),
('Sensor',2.5, '2017-01-01 00:02:15'),
('Sensor',3, '2017-01-01 00:02:56'),
('Sensor',3.5, '2017-01-01 00:03:27'),
('Sensor',4, '2017-01-01 00:04:01'),
('Sensor',5, '2017-01-01 00:05:00'),
('Sensor',5.5, '2017-01-01 00:05:15'),
('Sensor',5.5, '2017-01-01 00:05:46'),
('Sensor',6, '2017-01-01 00:06:10'),
('Sensor',7, '2017-01-01 00:06:57'),
('Sensor',7.5, '2017-01-01 00:07:13'),
('Sensor',8, '2017-01-01 00:08:01'),
('Sensor',9, '2017-01-01 00:09:03')
INSERT INTO [TempTargetTable]
([TargetTime])
VALUES
('2017-01-01 00:00:00'),
('2017-01-01 00:01:00'),
('2017-01-01 00:02:00'),
('2017-01-01 00:03:00'),
('2017-01-01 00:04:00'),
('2017-01-01 00:05:00'),
('2017-01-01 00:06:00'),
('2017-01-01 00:07:00'),
('2017-01-01 00:08:00'),
('2017-01-01 00:09:00')
答案 0 :(得分:1)
对于您发布的当前问题(简化版),我执行了以下操作:
交叉加入表格以使每个目标时间与每个现有数据时间戳相区别。
然后应用DENSE_RANK
函数,该函数将为每个TargetTime提供排名,然后仅选择具有最小差异(毫秒)的那些记录。
您可以找到有效的解决方案here。
select TargetIndex, TargetTime, DataIndex, DataName, DataValue, DataTimeStamp
from
(
select t.*, DENSE_RANK() OVER(PARTITION BY t.targetindex ORDER BY t.diff) as Rank
from
(
select tg.targetindex, tg.targettime, t.dataindex, t.dataname, t.datavalue, t.datatimestamp, abs(datediff(ms, tg.TargetTime, t.DataTimeStamp)) diff
from TempDataTable t cross join TempTargetTable tg
) t
) f
where Rank = 1
答案 1 :(得分:0)
如果您想要每个日历分钟中的第一条记录,可以使用arr
:
arr[id]
答案 2 :(得分:0)
如果我正在阅读您的问题,那么即使是在前一分钟,您也希望获得最接近的记录。如果是这样,你可以这个查询。我分多步完成,所以你可以轻松地跟随(我希望)
我做了什么:
查询
SELECT tempd.TargetTime, tdfinal.DataName, tdfinal.DataValue, tdfinal.DataTimeStamp
FROM @TempTargetTable as tempd
LEFT OUTER JOIN
(SELECT tdseconds.*, ROW_NUMBER() OVER(PARTITION BY closestMinute ORDER BY secondDiff) AS r
FROM (SELECT td.*, ABS(DATEDIFF(SECOND, DataTimeStamp, closestMinute)) AS secondDiff
FROM (SELECT DataName,DataValue,DataTimeStamp,
CONVERT(DATETIME,CONVERT(DATE, datatimestamp, 121)) +
CONVERT (DATETIME,TIMEFROMPARTS(DATEPART(HOUR, datatimestamp),
CASE WHEN DATEPART(SECOND, DataTimeStamp) >= 30
THEN DATEPART(MINUTE, DATATimeStamp) + 1
ELSE DATEPART(MINUTE, DATATimeStamp) END, 0,0,0), 121) AS closestMinute
FROM @TempDataTable ) AS td
) AS tdseconds
) AS tdfinal
ON tdfinal.closestMinute = tempd.TargetTime
WHERE tdfinal.r = 1
结果
TargetTime DataName DataValue DataTimeStamp
2017-01-01 00:00:00.000 Sensor 0.00 2017-01-01 00:00:00.000
2017-01-01 00:01:00.000 Sensor 1.00 2017-01-01 00:01:03.000
2017-01-01 00:02:00.000 Sensor 2.00 2017-01-01 00:02:01.000
2017-01-01 00:03:00.000 Sensor 3.00 2017-01-01 00:02:56.000
2017-01-01 00:04:00.000 Sensor 4.00 2017-01-01 00:04:01.000
2017-01-01 00:05:00.000 Sensor 5.00 2017-01-01 00:05:00.000
2017-01-01 00:06:00.000 Sensor 6.00 2017-01-01 00:06:10.000
2017-01-01 00:07:00.000 Sensor 7.00 2017-01-01 00:06:57.000
2017-01-01 00:08:00.000 Sensor 8.00 2017-01-01 00:08:01.000
2017-01-01 00:09:00.000 Sensor 9.00 2017-01-01 00:09:03.000