在每个开启事件之后,返回下一个关闭事件。

编程语言 2026-07-07

我正在查询存储在GridDB的运动传感器数据。每一行代表一个传感器状态的变化。

示例数据:

时间戳 状态
2021-06-30 10:00:00 开启
2021-06-30 10:00:13 关闭
2021-06-30 10:04:57 开启
2021-06-30 10:24:47 关闭
2021-06-30 10:31:20 开启

对于每个开启事件,我希望返回下一个关闭事件的时间戳。

预期输出:

开启时间 关闭时间
2021-06-30 10:00:00 2021-06-30 10:00:13
2021-06-30 10:04:57 2021-06-30 10:24:47
2021-06-30 10:31:20 NULL

这就是我当前正在使用的查询:```sql SELECT a.dt AS on_time, ( SELECT MIN(dt) FROM sensor_table WHERE dt > a.dt AND message = 'OFF' ) AS off_time FROM sensor_table AS a WHERE a.message = 'ON' ORDER BY a.dt;


在我的示例数据中可以返回预期的结果,但我在怀疑这是否是 GridDB 的正确 SQL 模式。

使用带有 MIN(dt) 的相关子查询来检索下一条匹配的行,是推荐做法吗,还是在 GridDB SQL 中有更地道或更高效的方法?

## 解决方案

我发现解决这类问题有两种不同的方法:一种是你的方法,使用子查询并通过对 off 事件进行累计求和来人为地对 on-off 事件进行分组。

不幸的是 GridDB 的 SQL 功能非常有限,无法创建这样的分组。要么在 From 子句中需要使用子查询[不支持],要么在累计求和之后再进行额外的算术运算[不支持]。这使得在这个数据库实现中第一种方法不可行。

于是只剩下你那种方法——关联子查询。通常来说,我会避免把子查询放在 Select 列表中,因为它们通常在每次检索表的一行时迭代执行,效率可能很慢。一个更标准的解法是把“开启”与“关闭”连接起来,并在 Where 子句中放入相关子查询以约束返回的行数。就你的情况来说

Select a.dt as on_time, b.dt as off_time From sensor_table a Left Outer Join sensor_table b Where a.message='on' and b.message='off' and b.dt=(Select min(x.dt) From sensor_table x Where x.message='off' and x.dt>a.dt) ```

我不是说这种写法一定会更高效,但与你将子查询放在Select子句中的情况相比,采用这种方法更有机会触发Select优化。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章