【问题标题】:Assign values lead / lag like within one table在一个表中分配值领先/滞后
【发布时间】:2026-01-11 03:15:01
【问题描述】:

我正在努力解决一个问题,如果最好使用 SQL 而不是 python/bash 脚本来解决的话。 这个想法是为状态 NO 计算每个对象的状态之间的时间差。我正在考虑添加第四列,并且我设法做了一些事情,但即使在很短的时间内它的工作速度也很慢(不可能以 5-10 分钟的间隔运行它)。 我正在使用 MySQL 5.7。

表格如下所示:

EVENT OBJECT STATE TIMESTAMP
1 CAR NO 25.01.2022 10:00
2 LAMP NO 25.01.2022 10:00
3 CAR OK 25.01.2022 10:05
4 CAR NO 25.01.2022 10:08
5 CAR OK 25.01.2022 10:10
6 LAMP OK 25.01.2022 10:30
7 LAMP NO 25.01.2022 10:32
8 WINDOW NO 25.01.2022 10:10
9 WINDOW OK 25.01.2022 10:20
10 LAMP OK 25.01.2022 10:50

想要的表:

EVENT OBJECT STATE TIMESTAMP TIMEDIF
1 CAR NO 25.01.2022 10:00 5
2 LAMP NO 25.01.2022 10:00 30
4 CAR NO 25.01.2022 10:08 2
7 LAMP NO 25.01.2022 10:32 18
8 WINDOW NO 25.01.2022 10:10 10

我的 SQL 示例:

SELECT 
  EVENT, 
  OBJECT, 
  STATE, 
  TIMESTAMP, 
  (
    (
      select 
        min(TIMESTAMP) 
      from 
        events events2 
      where 
        events1.OBJECT = events2.OBJECT 
        and events2.EVENT > events1.EVENT 
        and events2.STATE = 'NO'
    )
  ) STATE_NO 
FROM 
  events events1 
WHERE 
  events1.OBJECT = 'YES' "

提前谢谢你!

更新: 实际查询的解释(时间间隔-20天):

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY events1 NULL ALL events_1,events_2 NULL NULL NULL 5088944 1.08 Using where; Using temporary
1 PRIMARY t NULL eq_ref PRIMARY PRIMARY 8 zabbix.comtab.objectid 1 29.63 Using where
1 PRIMARY f NULL ref functions_1,functions_2 functions_1 8 zabbix.comtab.objectid 1 100.00 NULL
1 PRIMARY i NULL eq_ref PRIMARY,items_1 PRIMARY 8 zabbix.f.itemid 1 100.00 NULL
1 PRIMARY h NULL eq_ref PRIMARY PRIMARY 8 zabbix.i.hostid 1 10.00 Using where
2 DEPENDENT SUBQUERY events2 NULL ALL PRIMARY NULL NULL NULL 5088944 0.11 Range checked for each record (index map: 0x1)

实际查询中的联表不会影响性能。

【问题讨论】:

  • '我正在使用 MySQL 6.0' - 没有 mysql 版本 6 吗?
  • 其实是 mysql Ver 14.14 Distrib 5.7.19-17,适用于 Linux (x86_64) 使用 6.0,对不起! 5.7
  • 那么领先和落后是不可能的——你能升级到8吗?
  • 不,这是不可能的。问题是将状态 YES 的时间戳分配给 NO,如您在所描述的表格中所见。
  • 请重新检查您的 SQL。你确定这在逻辑上是正确的吗? WHERE events1.OBJECT = 'YES' 似乎不正确。你怎么能用这种逻辑得到任何结果?除此之外,对于性能问题,请提供确切的架构(创建表语句,带索引),以及结果:EXPLAIN SELECT ...

标签: mysql sql subquery nested-query


【解决方案1】:

让我们扭转局面。与其事后计算信息,不如在新数据到达时计算。并且,让我们有一个新表Current,其中包含每个传感器的当前状态。这是对History(就像你现在拥有的一样)和Desired 的补充。

当出现新的传感器状态并显示OK 时,请检查Current 是否为该设备显示NO。这是一个微不足道的SELECT。如果从NO 更改为OK,则INSERT 一行变为Desired。 (也是微不足道的。)

或者这可以体现在触发器 (ON UPDATE of Current) 中,使用OLD.state = 'NO' AND NEW.state = 'OK',加上TO_SECONDS(NEW.timestamp) - TO_SECONDS(OLD.timestamp) 作为timediff

如果您已经拥有大量数据并且需要构建Current,我会假装“重播”所有History。由于这是一次性设置,因此性能不是问题。

【讨论】:

    最近更新 更多