我有两张桌子:
是否有查询可以获取所有用户在活动中的开始和结束时间?
以下是数据样本:
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的答案。)
答案 0 :(得分:2)
试试这个 - 我想你可以从中得到你想要的东西。我使用了一个临时表,如果你愿意,你可以通过多种方式避免使用临时表,但我认为这样可以更容易地进行可视化。我也可以考虑一些优化,但这对于不太大的数据集也可以正常工作。可能还有一些我没想到的边界条件。好的,我能否再次获得答案。 。
--1.Get into temp table
select e.event_id, l.user_id,l.timestamp into #temp from locations l
left join events e on l.timestamp between e.begin_time and e.end_time
and l.latitude between e.min_latitude and e.max_latitude
and l.longitude between e.min_longitude and e.max_longitude
--2.Get when entered and left event
Select t1.*,
CASE WHEN t1.event_id is not null and isnull(t2.event_id,0)<>t1.event_id
THEN 'Yes' ELSE 'No' END As EnteredEvent,
CASE WHEN isnull(t1.event_id,0)<>isnull(t2.event_id,-1) and t2.event_id is not null
THEN 'Yes' ELSE 'No' END As LeftEvent
from
(SELECT t1.*, (
SELECT max(timestamp) as t22
FROM #temp t2
WHERE t1.user_id=t2.user_id and t2.timestamp < t1.timestamp
) as priortimestamp
FROM #temp t1) as t1
LEFT JOIN #temp t2 ON t1.user_id=t2.user_id and t1.priortimestamp=t2.timestamp
ORDER BY t1.user_id, t1.timestamp,t1.event_id
希望这有帮助
答案 1 :(得分:0)
您可以尝试此查询吗,
select user_id, MIN(timestamp) as enteredtime, MAX(timestamp) as exittime
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
GROUP BY locations.user_id
您可以在http://sqlfiddle.com/#!2/e8ba2/1看到该演示,希望它有用