sql - 提取每 2 个样本之间时间差最小的数据
问题描述
我有一个带有示例时间戳的表:
create table #OREN_TEMP(TS datetime)
insert into #OREN_TEMP(TS)
values
('2019-10-25 06:20:07.000'),
('2019-10-25 06:20:15.000'),
('2019-10-25 06:20:19.000'),
('2019-10-25 06:20:26.000'),
('2019-10-25 06:20:26.000'),
('2019-10-25 06:20:34.000'),
('2019-10-25 06:20:42.000'),
('2019-10-25 06:20:51.000'),
('2019-10-25 06:20:59.000'),
('2019-10-25 06:21:07.000'),
('2019-10-25 06:21:15.000'),
('2019-10-25 06:21:19.000'),
('2019-10-25 06:21:26.000')
select * from #OREN_TEMP
当一个样本与另一个样本之间的最短时间为 20 秒时,我被要求从表中提取数据。这意味着我需要提取以下内容:
('2019-10-25 06:20:07.000')
('2019-10-25 06:20:34.000')
('2019-10-25 06:20:59.000')
('2019-10-25 06:21:19.000')
我尝试执行以下操作:
declare @MIN_DATE datetime
select top 1 @MIN_DATE =TS from #OREN_TEMP
order by TS
select TS
from (select TS, row_number() over (partition by datediff(second,@MIN_DATE,TS) / 20 order by TS) as RowNum
from #OREN_TEMP
) TMP
where TMP.ROWNUM=1
我得到了:
TS
2019-10-25 06:20:07.000
2019-10-25 06:20:34.000
2019-10-25 06:20:51.000 -- Not good - only 17 seconds from previous
2019-10-25 06:21:07.000 -- Not good - only 16 seconds from previous
但这并没有帮助,因为我根据第一个 TS 而不是最后一个来划分时间框架。
我想避免循环或光标。与表本身的内部连接是可以的。
我该怎么做?我使用的是 SQL Server 2012 标准版。
解决方案
您可以为此使用递归 CTE。但它在 SQL Server 中效率不高。SQL Server 对递归 CTE 有许多限制,包括在子查询中没有聚合和递归引用。
所以,这里有一个版本:
with first_row as (
select top (1) ot.*
from oren_temp ot
order by ts asc
),
cte as (
select ts, 1 as lev
from first_row
union all
select ot.ts, lev + 1
from oren_temp ot join
cte
on ot.ts >= dateadd(second, 20, cte.ts)
)
select lev, min(ts)
from cte
group by lev;
不过,我会提醒您不要在行数过多的数据集上运行它。
编辑:
其实还有更有效的方法。在每个递归步骤中,我们可以ts
使用row_number()
:
with first_row as (
select top (1) ot.*
from oren_temp ot
order by ts asc
),
cte as (
select ts, 1 as lev, convert(int, 1) as seqnum
from first_row
union all
select ot.ts, lev + 1, convert(int, row_number() over (partition by lev order by ot.ts)) as seqnum
from oren_temp ot join
cte
on ot.ts >= dateadd(second, 20, cte.ts)
where seqnum = 1
)
select lev, ts, seqnum
from cte
where seqnum = 1;
这对更大的数据应该更有效。而且,它也很酷。
推荐阅读
- typescript - “elementfinder”类型的参数不能分配给“boolean”类型的参数
- django - 尝试访问 api 时,Django_hosts 集成会产生“NoReverseMatch at /en/api/”
- python - 当脚本在多处理工作人员中运行异步事件循环时,通过子进程运行脚本会挂起
- javascript - .findOne 函数,试图有多个参数
- python - 无法导入 Python 模块
- postgresql - 如何在 Windows 上使用 pg_squeeze
- php - PHP如何在数组中设置手动键值而不是多维数组中的索引?
- scala - 如何找到2个变量中存在的2个lat lng之间的距离哪个2个变量的数组
- java - 我有这个错误:java.sql.SQLException:Java 应用程序中的列名无效
- php - 我想通过一个信号向特定用户发送通知