【问题标题】:TIMEDIFF() between records that have one value and the other, not just oneTIMEDIFF() 在具有一个值和另一个值的记录之间,而不仅仅是一个
【发布时间】:2014-05-27 13:29:34
【问题描述】:

我有一个记录项目状态的表:

CREATE TABLE `project_states` (
    `id` INT(10) NOT NULL AUTO_INCREMENT,
    `state_id` INT(10) NULL DEFAULT NULL,
    `project_id` INT(10) NULL DEFAULT NULL,
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB

一些假数据:

    id  | state_id | project_id | created_at
-----------------------------------------------------
     1  |   2      |   8        | 2014-05-27 10:58:12   
     2  |   3      |   8        | 2014-05-27 11:10:34
     3  |   8      |   8        | 2014-05-27 11:56:48
     4  |   2      |  10        | 2014-05-27 11:08:34
     5  |   4      |  10        | 2014-05-27 11:59:01

我正在尝试获取两个状态(例如,2 和 8)之间的时间差,并且仅适用于 确实具有两种状态的项目;在这种情况下,仅适用于项目 8(因为 10 没有状态 8)。

到目前为止,我很成功地选择了符合条件的项目(同时具有两个值,而不仅仅是一个),但是这个查询为每个匹配的项目返回一个结果元组:

SELECT t.*
   FROM (
     SELECT ps.*
     FROM project_states ps
     WHERE ps.state_id IN (2,8) 
   ) as t
JOIN project_states pro ON pro.project_id = t.project_id
WHERE pro.state_id = 8

正确返回:

    id  | state_id | project_id | created_at
-----------------------------------------------------
     1  |   2      |   8        | 2014-05-27 10:58:12   
     3  |   8      |   8        | 2014-05-27 11:56:48

我很确定它可以工作,因为如果我将缺失的状态添加到另一个项目,它会返回新的结果元组:

    id  | state_id | project_id | created_at
-----------------------------------------------------
     1  |   2      |   8        | 2014-05-27 10:58:12   
     3  |   8      |   8        | 2014-05-27 11:56:48
     4  |   2      |  10        | 2014-05-27 11:08:34
     6  |   8      |  10        | 2014-05-27 12:03:08

但是如何计算时差?我正在使用 PHP,我知道我可以通过 project_id 遍历结果并 then 计算差异,但我认为可能有一个纯 SQL 解决方案可以产生如下结果:

project_id | difference
------------------------
     8     | 0000-00-00 01:02:00
    10     | 0000-00-00 01:05:26

嗯,实际上我的目标是计算项目在这两个选定状态之间的平均时间差,因此所有记录都可以归结为一个平均值,但这可能是我以后发现的问题。

【问题讨论】:

    标签: php mysql sql date-math


    【解决方案1】:

    如果您只有 2 个状态,则可以使用简单的 INNER JOIN。和TIMESTAMPDIFF() 以分钟为单位获得差异,例如:

    SELECT p.project_id,
           TIMESTAMPDIFF(MINUTE,p.created_at,p1.created_at) 
              as state_minutes_diff
    
    FROM project_states as p
    JOIN project_states as p1 
      ON p.project_id=p1.project_id
         AND p1.state_id=8  
    
    WHERE p.state_id=3
    

    SQLFiddle demo

    要获得所有项目的平均值:

    SELECT AVG(TIMESTAMPDIFF(MINUTE,p.created_at,p1.created_at))
              as AVG_state_minutes_diff
    FROM project_states as p
    JOIN project_states as p1 
      ON p.project_id=p1.project_id
         AND p1.state_id=8  
    WHERE p.state_id=3
    

    SQLFiddle demo

    【讨论】:

    • 谢谢,您的最后一个解决方案似乎很完美!
    【解决方案2】:

    我会使用聚合和有子句来做到这一点:

    select ps.project_id,
           timestampdiff(second, min(case when ps.state_id = 2 then created_at end),
                         max(case when ps.state_id = 8 then created_at)
                        ) as diff_in_secs
    
    from project_states ps
    where ps.state_id in (2, 8)
    group by ps.project_id
    having count(distinct ps.state_id) = 2;
    

    您也可以通过连接来做到这一点:

    select ps2.project_id, timestampdiff(second, ps2.created_at, ps8.created_at)
    from project_states ps2 join
         project_states ps8
         on ps2.project_id = ps8.project_id and
            ps2.state_id = 2 and ps8.state_id = 8;
    

    【讨论】:

      【解决方案3】:

      实际上,您不需要JOIN,因为您可以通过指定正确的GROUP BY 子句来解决问题:

      SELECT
        SEC_TO_TIME(AVG(times.atime)) AS avg_time
      FROM
        (SELECT
          project_id,
          TIMEDIFF(MAX(created_at), MIN(created_at)) AS atime
        FROM
          project_states
        WHERE
          state_id IN (2,8)
        GROUP BY
          project_id
        HAVING
          COUNT(DISTINCT id)>1) as times
      

      看来我迟到了,但至少,那是因为我做了fiddle

      【讨论】:

        【解决方案4】:
        SELECT project_id,
               timediff(min(created_at), max(created_at)) as difference
        FROM project_states
        WHERE state_id IN (2,8) 
        GROUP BY project_id 
        having count(distinct state_id) = 2
        

        【讨论】:

          猜你喜欢
          • 2019-06-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-05
          • 1970-01-01
          • 2021-06-14
          相关资源
          最近更新 更多