Tạo chế độ xem có tên home_to_work:
CREATE VIEW `home_to_work`AS
SELECT b.name, NULL AS `home`, b.timestamp AS `work`
FROM mytable b
WHERE b.location = 'work'
AND NOT EXISTS (
SELECT 1 FROM mytable m
WHERE b.name = m.name AND m.timestamp < b.timestamp
)
UNION ALL
SELECT a.name, a.timestamp AS `home`, b.timestamp AS `work`
FROM mytable a
JOIN mytable b
ON a.name = b.name AND a.location = 'home' AND b.location = 'work'
AND a.timestamp < b.timestamp
AND NOT EXISTS (
SELECT 1 FROM mytable m
WHERE a.name = m.name AND m.timestamp > a.timestamp AND m.timestamp < b.timestamp
)
UNION ALL
SELECT a.name, a.timestamp AS `home`, NULL AS `work`
FROM mytable a
WHERE a.location = 'home'
AND NOT EXISTS (
SELECT 1 FROM mytable m
WHERE a.name = m.name AND m.timestamp > a.timestamp
);
và một chế độ xem được gọi là work_to_home:
CREATE VIEW `work_to_home`AS
SELECT b.name, NULL AS `work`, b.timestamp AS `home`
FROM mytable b
WHERE b.location = 'home'
AND NOT EXISTS (
SELECT 1 FROM mytable m
WHERE b.name = m.name AND m.timestamp < b.timestamp
)
UNION ALL
SELECT a.name, a.timestamp AS `work`, b.timestamp AS `home`
FROM mytable a
JOIN mytable b
ON a.name = b.name AND a.location = 'work' AND b.location = 'home'
AND a.timestamp < b.timestamp
AND NOT EXISTS (
SELECT 1 FROM mytable m
WHERE a.name = m.name AND m.timestamp > a.timestamp AND m.timestamp < b.timestamp
)
UNION ALL
SELECT a.name, a.timestamp AS `work`, NULL AS `home`
FROM mytable a
WHERE a.location = 'work'
AND NOT EXISTS (
SELECT 1 FROM mytable m
WHERE a.name = m.name AND m.timestamp > a.timestamp
);
sau đó sử dụng truy vấn này:
SELECT `name`, location, `from`, `until`, duration
FROM (
SELECT h2w.`name`, 'work' AS `location`, h2w.work AS `from`, w2h.work AS `until`, TIMESTAMPDIFF(second, h2w.`work`, w2h.`work`) AS `duration`
FROM home_to_work h2w
JOIN work_to_home w2h
ON h2w.name = w2h.name AND h2w.work < w2h.work AND NOT EXISTS (
SELECT 1 FROM mytable m
WHERE h2w.name = m.name AND m.location = 'home' AND m.timestamp > h2w.work AND m.timestamp < w2h.work
)
UNION ALL
SELECT w2h.`name`, 'home' AS `location`, w2h.home AS `from`, h2w.home AS `until`, TIMESTAMPDIFF(second, w2h.`home`, h2w.`home`) AS `duration`
FROM work_to_home w2h
JOIN home_to_work h2w
ON w2h.name = h2w.name AND w2h.home < h2w.home AND NOT EXISTS (
SELECT 1 FROM mytable m
WHERE w2h.name = m.name AND m.location = 'work' AND m.timestamp > w2h.home AND m.timestamp < h2w.home
)
) locations
ORDER BY `name`, `from`
Giải thích:Tôi lấy các quá trình chuyển đổi từ nhà đến cơ quan và từ cơ quan về nhà (bao gồm chuyển đổi từ nhà đến nhà / cơ quan ban đầu và nhà / cơ quan cuối cùng thành rỗng) và sau đó tham gia các quá trình chuyển đổi này trong khi kiểm tra xem chúng có liên tiếp hay không.
Đây là SQL Fiddle .
Chỉnh sửa trong câu trả lời cho nhận xét của bạn:
Dễ dàng tìm được vị trí đã biết cuối cùng cho một người và thời gian nhất định:
SELECT location
FROM mytable
WHERE `name` = 'John' AND timestamp < '2015-07-08 11:07:00'
ORDER BY timestamp DESC
LIMIT 1