我正在为基于位置的检查构建一个Web应用程序,有点像本地4square,但基于RFID标签。
无论如何,每个签到都存储在MySQL表中,其中包含userID和签入时间作为DATETIME列。
现在,我想说明哪些用户在不同电台之间的登机时间最近。
说明:假设用户A在21:43:12签到,然后又在21:43:19签到。他在7秒内在车站之间移动。
数据库中有成千上万的签到,如何编写SQL来选择具有两个最接近的签到时间的用户?
答案 0 :(得分:1)
试试这个:
select
a.id,
b.id,
abs(a.rfid-b.rfid)
from
table1 a,
table1 a
where
a.userID=b.userID
// and any other conditions to make it a single user
group by
a.id,
b.id,
a.rfid,
b.rfid
order by
abs(a.rfid-b.rfid) desc
limit 1
答案 1 :(得分:1)
真正快速的解决方案会引入一些预先计算。就像存储当前和以前的签到之间的差异一样。
在这种情况下,您可以快速选择所需内容(只要您按索引覆盖该列)。
在这种情况下不使用预先计算会导致可疑的查询,这些查询将在类似笛卡尔的制作中运行。
答案 2 :(得分:0)
你有什么尝试?你看过DATEDIFF了吗? http://msdn.microsoft.com/en-us/library/ms189794.aspx
干杯 --Jocke
答案 3 :(得分:0)
首先,您需要用户的索引,然后是时间戳。
其次,您需要使用相关的子查询来查找“下一个时间戳”。
然后使用GROUP BY查找每个用户的最小间隔。
SELECT
a.user_id,
MIN(TIMEDIFF(b.timestamp, a.timestamp)) AS min_duration,
FROM
checkin AS a
INNER JOIN
checkin AS b
ON b.user_id = a.user_id
AND b.timestamp = (SELECT MIN(timestamp)
FROM checkin
WHERE user_id = a.user_id
AND timestamp > a.timestamp)
GROUP BY
a.user_id
ORDER BY
min_duration
LIMIT
1
如果您想允许具有相同min_duration
的多个用户,我建议将结果(不带LIMIT 1
)存储在临时表中,然后搜索该表适用于所有共享最短持续时间的用户。
根据数据量,这可能会很慢。一个优化是缓存TIMEDIFF()
的结果。每次记录新的登记时,还要计算并存储自上次登记以来的持续时间,也许使用触发器。预先计算后,查询更简单,值可转换。
答案 4 :(得分:0)
我想,你只想计算两张签到之间的差异,如果他们是同一个人的两个连续签到。
create table test (
id int,
person_id int,
checkin datetime);
insert into test (id, person_id, checkin) values (1, 1, now());
insert into test (id, person_id, checkin) values (2, 1, now());
insert into test (id, person_id, checkin) values (3, 2, now());
insert into test (id, person_id, checkin) values (4, 2, now());
insert into test (id, person_id, checkin) values (5, 1, now());
insert into test (id, person_id, checkin) values (6, 2, now());
insert into test (id, person_id, checkin) values (7, 1, now());
select * from (
select a.*,
(select a.checkin - b.checkin
from test b where b.person_id = a.person_id
and b.checkin < a.checkin
order by b.checkin desc
limit 1
) diff
from test a
where a.person_id = 1
order by a.person_id, a.checkin
) tt
where diff is not null
order by diff asc;
答案 5 :(得分:0)
SELECT a.*, b.*
FROM table_name AS a
JOIN table_name AS b
ON a.id != b.id
ORDER BY TIMESTAMPDIFF(SECOND, a.checkin, b.checkin) ASC
LIMIT 1
应该这样做。如上所述,可能会有点滞后。