Sprawdź to:
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 służy tylko do widoczności — możesz połączyć wszystko w jedno zapytanie.