MySQL select 在特定规则的行之后
MySQL select after row on specific rules
我有一个 table 这样的:
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', 'away', '2021-01-02 04:08:00'),
('10', 'break', '2021-01-02 04:10:00'),
('11', 'online', '2021-01-02 04:15:00'),
('12', 'logout', '2021-01-02 04:55:00'),
('13', 'login', '2021-01-02 05:04:00'),
('14', 'online', '2021-01-02 05:05:00'),
('15', 'away', '2021-01-03 05:01:00'),
('16', 'logout', '2021-01-03 05:02:00'),
('17', 'login', '2021-01-03 05:04:00'),
('18', 'online', '2021-01-03 05:05:00'),
('19', 'logout', '2021-01-04 03:05:00'),
('20', 'login', '2021-01-04 05:07:00'),
('21', 'online', '2021-01-04 06:00:00'),
('22', 'logout', '2021-01-05 10:00:00'),
('23', 'login', '2021-01-05 11:00:00'),
('24', 'away', '2021-01-05 11:01:00'),
('25', 'online', '2021-01-06 06:01:00'),
('26', 'login', '2021-01-07 06:01:00'),
('26', 'logout', '2021-01-07 07:01: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
......
在上面的插入查询中提供的数据。
我想要一个输出:
date
A (online)
B (Logout)
2021-01-01
2021-01-02 04:07:00
2021-01-02 04:55:00
2021-01-02
2021-01-02 05:05:00
2021-01-03 04:59:59
2021-01-03
2021-01-03 05:05:00
2021-01-04 03:05:00
2021-01-04
2021-01-04 06:00:00
2021-01-04 04:59:59
2021-01-05
2021-01-04 05:00:00
2021-01-05 10:00:00
2021-01-06
2021-01-04 11:00:00
2021-01-06 04:59:59
规则是,1 个记录日是从 5:00:00 -(次日)04:59:59。
'A'是从上次上线开始的时间戳(登录后,如果有的话),'B'是从上次注销开始的时间戳(如果没有注销,B设置为04:59:59。
另一个规则是,如果最后一天在'online'之后没有'logout',则计算到下一个日志日(下一个日志日设置为05.00.00,如果最后一条记录来自最后记录日是 'online')
目前我正在使用此查询来应用记录日规则:
SELECT date(t1.timestamp) dt, (t2.timestamp) A, (t3.timestamp) B, t1.status, t2.status, t3.status
FROM logging t1
JOIN logging t2 ON t1.timestamp < t2.timestamp
JOIN logging t3 ON t2.timestamp < t3.timestamp
WHERE
t1.status = 'login'
AND t2.status = 'online'
AND t3.status = 'logout'
AND NOT EXISTS ( SELECT NULL
FROM loggingt4
WHERE t1.timestamp < t4.timestamp
AND t4.timestamp < t2.timestamp
AND t4.status IN ('login', 'online', 'logout') )
AND NOT EXISTS ( SELECT NULL
FROM logging t5
WHERE t2.timestamp < t5.timestamp
AND t5.timestamp < t3.timestamp
AND t5.status IN ('login', 'logout'))
AND DATE(t1.timestamp - INTERVAL 6 HOUR) = DATE(t3.timestamp - INTERVAL '05:59:59' HOUR_SECOND);
检查这个:
WITH cte AS (
SELECT DATE(t1.`timestamp` - INTERVAL 5 HOUR) `date`,
MAX(t1.`timestamp`) login,
MAX(t2.`timestamp`) online,
MAX(t3.`timestamp`) logout
FROM logging t1
JOIN logging t2 ON t1.`timestamp` < t2.`timestamp`
JOIN logging t3 ON t2.`timestamp` < t3.`timestamp`
WHERE t1.status = 'login'
AND t2.status = 'online'
AND t3.status = 'logout'
AND NOT EXISTS ( SELECT NULL
FROM logging t4
WHERE t1.`timestamp` < t4.`timestamp`
AND t4.`timestamp` < t2.`timestamp`
AND t4.status IN ('login', 'online', 'logout') )
AND NOT EXISTS ( SELECT NULL
FROM logging t5
WHERE t2.`timestamp` < t5.`timestamp`
AND t5.`timestamp` < t3.`timestamp`
AND t5.status IN ('login', 'logout') )
GROUP BY `date`
)
SELECT `date`,
online,
CASE WHEN DATE(online - INTERVAL 5 HOUR) = DATE(logout - INTERVAL '04:59:59' HOUR_SECOND)
THEN logout
ELSE DATE(online + INTERVAL 19 HOUR) + INTERVAL '04:59:59' HOUR_SECOND
END logout
FROM cte
CTE 仅用于可见性 - 您可以将所有内容合并到一个查询中。
我有一个 table 这样的:
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', 'away', '2021-01-02 04:08:00'),
('10', 'break', '2021-01-02 04:10:00'),
('11', 'online', '2021-01-02 04:15:00'),
('12', 'logout', '2021-01-02 04:55:00'),
('13', 'login', '2021-01-02 05:04:00'),
('14', 'online', '2021-01-02 05:05:00'),
('15', 'away', '2021-01-03 05:01:00'),
('16', 'logout', '2021-01-03 05:02:00'),
('17', 'login', '2021-01-03 05:04:00'),
('18', 'online', '2021-01-03 05:05:00'),
('19', 'logout', '2021-01-04 03:05:00'),
('20', 'login', '2021-01-04 05:07:00'),
('21', 'online', '2021-01-04 06:00:00'),
('22', 'logout', '2021-01-05 10:00:00'),
('23', 'login', '2021-01-05 11:00:00'),
('24', 'away', '2021-01-05 11:01:00'),
('25', 'online', '2021-01-06 06:01:00'),
('26', 'login', '2021-01-07 06:01:00'),
('26', 'logout', '2021-01-07 07:01: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 |
......
在上面的插入查询中提供的数据。
我想要一个输出:
date | A (online) | B (Logout) |
---|---|---|
2021-01-01 | 2021-01-02 04:07:00 | 2021-01-02 04:55:00 |
2021-01-02 | 2021-01-02 05:05:00 | 2021-01-03 04:59:59 |
2021-01-03 | 2021-01-03 05:05:00 | 2021-01-04 03:05:00 |
2021-01-04 | 2021-01-04 06:00:00 | 2021-01-04 04:59:59 |
2021-01-05 | 2021-01-04 05:00:00 | 2021-01-05 10:00:00 |
2021-01-06 | 2021-01-04 11:00:00 | 2021-01-06 04:59:59 |
规则是,1 个记录日是从 5:00:00 -(次日)04:59:59。 'A'是从上次上线开始的时间戳(登录后,如果有的话),'B'是从上次注销开始的时间戳(如果没有注销,B设置为04:59:59。 另一个规则是,如果最后一天在'online'之后没有'logout',则计算到下一个日志日(下一个日志日设置为05.00.00,如果最后一条记录来自最后记录日是 'online')
目前我正在使用此查询来应用记录日规则:
SELECT date(t1.timestamp) dt, (t2.timestamp) A, (t3.timestamp) B, t1.status, t2.status, t3.status
FROM logging t1
JOIN logging t2 ON t1.timestamp < t2.timestamp
JOIN logging t3 ON t2.timestamp < t3.timestamp
WHERE
t1.status = 'login'
AND t2.status = 'online'
AND t3.status = 'logout'
AND NOT EXISTS ( SELECT NULL
FROM loggingt4
WHERE t1.timestamp < t4.timestamp
AND t4.timestamp < t2.timestamp
AND t4.status IN ('login', 'online', 'logout') )
AND NOT EXISTS ( SELECT NULL
FROM logging t5
WHERE t2.timestamp < t5.timestamp
AND t5.timestamp < t3.timestamp
AND t5.status IN ('login', 'logout'))
AND DATE(t1.timestamp - INTERVAL 6 HOUR) = DATE(t3.timestamp - INTERVAL '05:59:59' HOUR_SECOND);
检查这个:
WITH cte AS (
SELECT DATE(t1.`timestamp` - INTERVAL 5 HOUR) `date`,
MAX(t1.`timestamp`) login,
MAX(t2.`timestamp`) online,
MAX(t3.`timestamp`) logout
FROM logging t1
JOIN logging t2 ON t1.`timestamp` < t2.`timestamp`
JOIN logging t3 ON t2.`timestamp` < t3.`timestamp`
WHERE t1.status = 'login'
AND t2.status = 'online'
AND t3.status = 'logout'
AND NOT EXISTS ( SELECT NULL
FROM logging t4
WHERE t1.`timestamp` < t4.`timestamp`
AND t4.`timestamp` < t2.`timestamp`
AND t4.status IN ('login', 'online', 'logout') )
AND NOT EXISTS ( SELECT NULL
FROM logging t5
WHERE t2.`timestamp` < t5.`timestamp`
AND t5.`timestamp` < t3.`timestamp`
AND t5.status IN ('login', 'logout') )
GROUP BY `date`
)
SELECT `date`,
online,
CASE WHEN DATE(online - INTERVAL 5 HOUR) = DATE(logout - INTERVAL '04:59:59' HOUR_SECOND)
THEN logout
ELSE DATE(online + INTERVAL 19 HOUR) + INTERVAL '04:59:59' HOUR_SECOND
END logout
FROM cte
CTE 仅用于可见性 - 您可以将所有内容合并到一个查询中。