如何组合两行并计算MySQL中两个时间戳值之间的时差?

Nad*_*dar 11 mysql sql

我有一种情况,我确信这是非常普遍的,我真的很困扰我,我无法弄清楚如何做或搜索什么来找到相关的示例/解决方案.我对MySQL比较陌生(之前一直在使用MSSQL和PostgreSQL),我能想到的每种方法都被MySQL缺乏的一些功能所阻挡.

我有一个"日志"表,它只是列出了许多不同的事件及其时间戳(存储为日期时间类型).表中有很多数据和列与此问题无关,因此我们假设我们有一个这样的简单表:

CREATE TABLE log (  
  id INT NOT NULL AUTO_INCREMENT,  
  name VARCHAR(16),  
  ts DATETIME NOT NULL,  
  eventtype VARCHAR(25),  
  PRIMARY KEY  (id)  
)
Run Code Online (Sandbox Code Playgroud)

假设某些行有一个eventtype ='start'而其他行有一个eventtype ='stop'.我想做的是以某种方式将每个"startrow"与每个"stoprow"结合起来并找到两者之间的时间差(然后将每个名称的持续时间相加,但这不是问题所在的位置).每个"开始"事件应该在某个阶段发生相应的"停止"事件,然后发生"开始"事件,但由于数据收集器出现问题/错误/崩溃,可能会丢失一些事件.在这种情况下,我想在没有"伙伴"的情况下忽视这一事件.这意味着给定数据:

foo, 2010-06-10 19:45, start  
foo, 2010-06-10 19:47, start  
foo, 2010-06-10 20:13, stop
Run Code Online (Sandbox Code Playgroud)

..我想忽略19:45开始事件而不是仅仅使用20:13停止事件作为停止时间获得两个结果行.

我试图以不同的方式加入表格,但对我来说关键问题似乎是找到一种方法来正确识别给定"名称"的"开始"事件的相应"停止"事件.这个问题与您在员工上下班的工作表并希望了解他们实际工作量有多少完全相同.我敢肯定必须有一个众所周知的解决方案,但我似乎无法找到它们......

Iva*_*sen 6

我相信这可能是实现目标的更简单方法:

SELECT
    start_log.name,
    MAX(start_log.ts) AS start_time,
    end_log.ts AS end_time,
    TIMEDIFF(MAX(start_log.ts), end_log.ts)
FROM
    log AS start_log
INNER JOIN
    log AS end_log ON (
            start_log.name = end_log.name
        AND
            end_log.ts > start_log.ts)
WHERE start_log.eventtype = 'start'
AND end_log.eventtype = 'stop'
GROUP BY start_log.name
Run Code Online (Sandbox Code Playgroud)

它应该运行得相当快,因为​​它消除了一个子查询.


Vot*_*ple 0

这个怎么样:

SELECT start_log.ts AS start_time, end_log.ts AS end_time
FROM log AS start_log
INNER JOIN log AS end_log ON (start_log.name = end_log.name AND end_log.ts > start_log.ts)
WHERE NOT EXISTS (SELECT 1 FROM log WHERE log.ts > start_log.ts AND log.ts < end_log.ts)
 AND start_log.eventtype = 'start'
 AND end_log.eventtype = 'stop'
Run Code Online (Sandbox Code Playgroud)

这将找到中间没有事件的每对行(别名为start_log和),其中第一行始终是开始,最后一个始终是停止。end_log由于我们不允许中间事件,因此自然会排除未立即停止的开始。