【发布时间】:2013-11-26 02:15:56
【问题描述】:
我有两张桌子:
- Locations - 存储用户的地理位置和时间戳。
- Events - 存储活动的地理范围以及摇滚音乐会活动的开始和结束时间。
是否有查询可以获取活动中所有用户的开始和结束时间?
以下是数据示例:
CREATE TABLE locations (
user_id INT NOT NULL,
timestamp DATETIME NOT NULL,
latitude FLOAT NOT NULL,
longitude FLOAT NOT NULL
);
INSERT INTO locations (user_id, timestamp, latitude, longitude)
VALUES
(1, '2013-11-22 01:12:23', 37.7674, -122.439),
(1, '2013-11-22 01:13:24', 37, -122),
(1, '2013-11-22 01:14:25', 37.7674, -122.439),
(2, '2013-11-25 01:12:23', 37.7674, -122.439),
(2, '2013-11-25 01:13:24', 37, -122),
(2, '2013-11-25 01:14:25', 37.7674, -122.439);
CREATE TABLE events (
event_id INT NOT NULL,
begin_time DATETIME NOT NULL,
end_time DATETIME NOT NULL,
min_latitude FLOAT NOT NULL,
max_latitude FLOAT NOT NULL,
min_longitude FLOAT NOT NULL,
max_longitude FLOAT NOT NULL
);
INSERT INTO events (event_id, begin_time, end_time, min_latitude, max_latitude, min_longitude, max_longitude)
VALUES
(1, '2013-11-22 01:00:00', '2013-11-22 02:00:00', 37.7673, 37.7675, -122.440, -122.439),
(2, '2013-11-25 01:00:00', '2013-11-25 02:00:00', 37.7674, 37.7674, -122.439, -122.439);
这个问题有两个部分:
- 第一部分涉及查找用户参加活动的所有行。
- 第二部分涉及查找用户输入事件的第一个时间戳(然后忽略用户留在事件中的所有后续行),然后获取用户离开事件的行。如果我们只获取用户在事件中的所有行,这将很容易。
以下内容将为我提供用户位置与事件重合的所有行。
select * from locations
join events on
locations.timestamp between events.begin_time and events.end_time and
locations.latitude between events.min_latitude and events.max_latitude and
locations.longitude between events.min_longitude and events.max_longitude
但是,我似乎无法找到一种仅获取用户在活动中的开始和结束时间的好方法。此外,(我不知道这是否会使问题更有趣)用户可以离开并返回到同一个事件。
(我使用的是 MySQL,但我会接受任何 SQL 风格的答案。)
【问题讨论】:
-
您是否尝试过按 user_id 和 event_id 分组并选择 min(timestamp) 和 max(timestamp)?
-
是的,感谢您的建议。不幸的是,这无法处理用户离开并返回到同一事件的情况。我想知道他们何时离开并返回参加活动,因此我们不会在这些时间向他们收费。
-
你怎么知道他们离开又回来了?你的表格没有说清楚。
-
是的,如果有任何不清楚的地方,我深表歉意。当我们按时间戳对
locations表进行排序时,如果latitude、longitude曾经在events范围内,然后在events范围之外,反之亦然。我们可以确定用户已经离开并返回到某个事件。谢谢。 -
这听起来像是一个“差距和岛屿”问题。这些similar questions 对你有帮助吗?
标签: sql gaps-and-islands