Search code examples
mysqldatetimejoinsql-timestamp

Select row after each condition from the same table myql


I have a table like this:

CREATE TABLE IF NOT EXISTS `logging` (
  `id` int(6) unsigned NOT NULL,
  `status` varchar(150) NOT NULL,
  `timestamp` DATETIME NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `logging` (`id`, `status`, `timestamp`) VALUES
  ('1', 'logout', '2021-01-01 05:01:00'),
  ('2', 'login', '2021-01-01 06:02:00'),
  ('3', 'online', '2021-01-01 06:03:00'),
  ('4', 'away', '2021-01-01 06:04:00'),
  ('5', 'online', '2021-01-01 06:05:00'),
  ('6', 'logout', '2021-01-02 04:00:00'),
  ('7', 'login', '2021-01-02 04:05:00'),
  ('8', 'online', '2021-01-02 04:07:00'),
  ('9', 'logout', '2021-01-02 04:55:00');
id status timestamp
1 logout 2021-01-01 05:01:00
2 login 2021-01-01 06:02:00
3 online 2021-01-01 06:03:00
4 away 2021-01-01 06:04:00
5 online 2021-01-01 06:05:00
6 logout 2021-01-02 04:00:00
7 login 2021-01-02 04:05:00
8 online 2021-01-02 04:07:00
9 logout 2021-01-02 04:55:00

i want to have an output:

date A B
2021-01-01 2021-01-01 06:03:00 2021-01-02 04:00:00
2021-01-02 ... ...
2021-01-03 ... ...

the rule is, 1 log day is from 5:00:00 - (next day) 04:49:49. 'A' is timestamp start from the first online (after login), 'B' is timestamp from the first logout (after online).

currently i'm using this query to apply the log day rule:

select dt, timestamp from ( 
    select id, left(timestamp, 10) dt, timestamp, status
    from logging
    where TIME(timestamp)  >= '05:00:00' and status = 'online'
    union all 
    select id, left((timestamp-interval 1 day), 10) dt ,timestamp, status
    from logging
    where TIME(timestamp)  < '05:00:00' and status = 'online'
    ) x group by dt;

But i have problem to apply the second rule to get the timestamp..

Updated: Here's the test data and table: https://www.db-fiddle.com/f/tDJL2JHwbtSNEurrLEj11r/0 or http://sqlfiddle.com/#!9/aadb80/2


Solution

  • SELECT t1.ts A, t3.ts B
    FROM test t1
    JOIN test t2 ON t1.ts < t2.ts
    JOIN test t3 ON t2.ts < t3.ts
    WHERE t1.status = 'login'
      AND t2.status = 'online'
      AND t3.status = 'logout'
      AND NOT EXISTS ( SELECT NULL
                       FROM test t4
                       WHERE t1.ts < t4.ts
                         AND t4.ts < t2.ts
                         AND t4.status IN ('login', 'online', 'logout') )
      AND NOT EXISTS ( SELECT NULL
                       FROM test t5
                       WHERE t2.ts < t5.ts
                         AND t5.ts < t3.ts
                         AND t5.status IN ('login', 'logout') )
      AND DATE(t1.ts - INTERVAL 5 HOUR) = DATE(t3.ts - INTERVAL '04:49:49' HOUR_SECOND);
    

    fiddle