2

查找具有相同值的相邻记录的开始和结束时间?

我有一个表格,其中包含心率读数(以每分钟节拍为单位)和日期时间字段。(实际上字段是heartrate_idheartratedatetime。)数据由每 6 秒记录一次心率和时间的设备生成。有时心率监测器会给出错误的读数,并且记录的每分钟心跳数会“粘住”一段时间。棒,我的意思是每分钟的节拍值在相邻的时间里是相同的。

基本上,我需要找到所有心率相同的记录(例如每分钟 5 次、每分钟 100 次等),但仅在相邻记录上。如果设备记录 3 次连续读数(或 100 次连续读数)每分钟 25 次心跳,我需要定位这些事件。结果需要有心率、心率开始时间和心率结束时间,理想情况下,结果看起来更像这样:

heartrate starttime endtime
--------- --------- --------
1.00      21:12:00  21:12:24
35.00     07:00:12  07:00:36

我已经尝试了几种不同的方法,但到目前为止我正在脱颖而出。任何帮助将不胜感激!

4

2 回答 2

3

编辑:

经过审查,我在这个答案上的原创作品都不是很好。这实际上属于被称为的一类问题,这个修订后的答案将使用我从第一次回答这个问题以来从类似问题中收集/学到的信息。

事实证明,这个查询比我最初想象的要简单得多

WITH Grouped_Run AS (SELECT heartRate, dateTime,
                            ROW_NUMBER() OVER(ORDER BY dateTime) -  
                            ROW_NUMBER() OVER(PARTITION BY heartRate ORDER BY dateTime) AS groupingId
                     FROM HeartRate)

SELECT heartRate, MIN(dateTime), MAX(dateTime)
FROM Grouped_Run
GROUP BY heartRate, groupingId
HAVING COUNT(*) > 2

SQL Fiddle Demo


那么这里发生了什么?差距和孤岛问题的定义之一是需要连续值的“组”(或缺少连续值)。通常会生成序列来解决这个问题,利用一个经常被忽视/过于直观的事实:减去序列会产生一个恒定值。

例如,想象以下序列和减法(行中的值不重要):

position   positionInGroup  subtraction
=========================================
1          1                0
2          2                0
3          3                0
4          1                3
5          2                3
6          1                5
7          4                3
8          5                3

position是在所有记录上生成的简单序列。
positionInGroup是为每组不同的记录生成的简单序列。在这种情况下,实际上有 3 组不同的记录(从 开始position = 1, 4, 6)。
subtraction是其他两列之间差异的结果。请注意,不同组的值可能会重复!
序列必须共享的关键属性之一是它们必须以相同的顺序在数据行上生成,否则会中断。

那么 SQL 是如何做到这一点的呢?通过使用ROW_NUMBER()此函数,将在记录“窗口”上生成一系列数字:

ROW_NUMBER() OVER(ORDER BY dateTime)

将生成position序列。

ROW_NUMBER() OVER(PARTITION BY heartRate ORDER BY dateTime)

将生成positionInGroup序列,每个序列heartRate都是不同的组。
对于这种类型的大多数查询,两个序列的值并不重要,重要的是减法(获取序列组),所以我们只需要减法的结果。
我们还需要heartRate他们发生的时间和时间来提供答案。

最初的答案要求每个“运行”卡住心跳的开始和结束时间。这是一个标准MIN(...)/ MAX(...),这意味着一个GROUP BY. 我们需要同时使用原始heartRate(因为这是一个非聚合列)我们生成的列groupingId(它标识每个卡住值的当前“运行”)。

部分问题只要求重复三次或更多次的运行。这HAVING COUNT(*) > 2是一条忽略长度为 2 或更短的运行的指令;它计算每组的行数。

于 2011-07-08T20:43:16.287 回答
0

我推荐 Ben-Gan 关于区间打包的文章,它适用于您的邻接问题。

tsql 挑战包装日期和时间间隔

包装日期和时间间隔拼图的解决方案

于 2011-07-20T20:00:48.717 回答