简体   繁体   中英

How to check values in mysql for preceeding rows and using them to find sum

I have to find the time, that the system that is based on this table has elapsed while having code '100', so firstly i thought that I have to find the newest row of the xID group and after that, check the previous rows if their code is 100, if so i have to proceed with previous previous row till it gets a 200 value, after that it finds the time from the following row of 200 hundred till now (value 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'

So this query must for each group of xID find the total time for which the system has been with code 100 until now. Hope I've been clear. And here is the sql so far.

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

EDIT: MYSQL VERSION 8.0 RESULT must be something like this where the column totTimeWithCode100 must show the time in seconds or minutes doesn't matter, for each type of xID.

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

These rows

Prior to MySQL 8.0, we can use of user-defined variables (in a way that is unsupported) in carefully crafted SQL that takes advantage of behavior that is repeatably observed but not guaranteed. (The MySQL Reference Manual warns specifically about this usage of user-defined variables.)

Something like this:

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

With MySQL 8.0, we can avoid the user-defined variables by using analytic/window functions.

You can get the result you want by finding all the rows with CODE = 100 for a given xID that are immediately followed (in time) by a row with CODE != 100 . This can be done by LEFT JOIN ing the rows with CODE != 100 to the preceding row if that row has 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM