如何在mysql中检查前面的行的值并使用它们查找总和

时间:2019-03-06 22:27:22

标签: mysql sql

我必须找到时间,该表基于系统的代码为100时已过去,所以首先我认为我必须找到xID组的最新行,然后检查前一行,如果它们的代码是100,那么如果要这样做,我必须继续上一行直到它得到200的值,之后,它才从下一行200开始查找到现在的时间(值100)。

ID     xID      createdDate          CODE
 1     '1', '2019-07-27 11:52:01',  '100'
 2     '1', '2019-07-27 11:54:01',  '200'
 3     '2', '2019-09-03 05:10:02',  '200'
 4     '2', '2019-09-03 05:12:02',  '200'
 5     '3', '2019-09-02 05:12:02',  '200'
 6     '3', '2019-09-02 05:12:02',  '100'
 7     '3', '2019-09-02 05:12:02',  '200'
 8     '4', '2019-09-02 05:13:02',  '200'
 9     '5', '2019-09-03 05:10:03',  '200'
 10    '6', '2018-12-13 05:03:02',  '200'

因此,此查询必须为每个xID组找到系统到目前为止使用代码100的总时间。希望我已经清楚了。这是到目前为止的sql。

select id, createdDate, code
from wlogs 
where id in (
select max(id)
from wlogs
group by xid
)
order by xid;

编辑: MYSQL版本8.0 对于每种类型的xID,结果必须是这样的,其中totTimeWithCode100列必须以秒或分钟为单位显示时间无关紧要。

xID   totTimeWithCode100
'1',   '500'   
'2',   '2'  
'3',   '33'
'4',   '200'
'5',   '40'
'6',   '200'

These rows

2 个答案:

答案 0 :(得分:0)

在MySQL 8.0之前,我们可以在精心设计的SQL中使用用户定义的变量(以不受支持的方式),该变量利用了可重复观察但不能保证的行为。 (《 MySQL参考手册》特别警告用户定义变量的用法。)

类似这样的东西:

SELECT s.xid                            AS `xID`
     , IFNULL(SUM(s.secs_in_code100),0) AS `totTimeWithCode100`
  FROM (
         SELECT IF(@prev_xid = t.xid AND @prev_code = 100, TIMESTAMPDIFF(SECOND,@prev_date,t.createddate),0) AS secs_in_code100
              , @prev_xid  := t.xid          AS xid
              , @prev_date := t.createddate  AS createddate 
              , @prev_code := t.code         AS code
           FROM ( SELECT @prev_xid  := ''
                       , @prev_date := '1970-01-02 03:00'
                       , @prev_code := ''
                ) i
          CROSS
           JOIN wlogs t
          ORDER
             BY t.xid
              , t.createddate
       ) s
 GROUP BY s.xid
 ORDER BY s.xid

在MySQL 8.0中,我们可以通过使用分析/窗口函数来避免用户定义的变量。

答案 1 :(得分:0)

通过找到给定CODE = 100的所有带有xID的行,然后立即(按时间)紧跟着CODE != 100的行,可以得到想要的结果。这可以通过LEFT JOIN将带有CODE != 100的行添加到前一行 来进行,如果该行具有CODE = 100

SELECT w.xID, COALESCE(SUM(TIMESTAMPDIFF(SECOND, w1.createdDate, w2.createdDate)), 0) AS totTimeWithCode100
FROM (SELECT DISTINCT xID FROM wlogs) w
LEFT JOIN (SELECT * 
           FROM wlogs
           WHERE CODE = 100) w1 ON w1.xID = w.xID
LEFT JOIN wlogs w2 ON w2.xID = w1.xID
                  AND w2.createdDate = (SELECT MIN(createdDate)
                                        FROM wlogs w3
                                        WHERE w3.xID = w1.xID AND
                                              w3.createdDate > w1.createdDate)
GROUP BY w.xID
ORDER BY w.xID;

Demo on dbfiddle