从同一个表中选择每个条件后的行 myql

问题描述

我有一张这样的桌子:

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','2021-01-01 06:05:00'),('6','2021-01-02 04:00:00'),('7','2021-01-02 04:05:00'),('8','2021-01-02 04:07:00'),('9','2021-01-02 04:55:00');
id 状态 时间戳
1 注销 2021-01-01 05:01:00
2 登录 2021-01-01 06:02:00
3 在线 2021-01-01 06:03:00
4 离开 2021-01-01 06:04:00
5 在线 2021-01-01 06:05:00
6 注销 2021-01-02 04:00:00
7 登录 2021-01-02 04:05:00
8 在线 2021-01-02 04:07:00
9 注销 2021-01-02 04:55:00

我想要一个输出

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

规则是,1 个日志日是从 5:00:00 -(第二天)04:49:49。 'A'是从第一次在线(登录后)开始的时间戳,'B'是从第一次退出(在线后)开始的时间戳。

目前我正在使用此查询来应用日志日规则:

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),status
    from logging
    where TIME(timestamp)  < '05:00:00' and status = 'online'
    ) x group by dt;

但是我在应用第二条规则来获取时间戳时遇到问题..

更新: 这是测试数据和表格:https://www.db-fiddle.com/f/tDJL2JHwbtSNEurrLEj11r/0http://sqlfiddle.com/#!9/aadb80/2

解决方法

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