如何找到哪两行的时间戳最接近?

时间:2012-08-03 12:21:59

标签: mysql sql

我正在为基于位置的检查构建一个Web应用程序,有点像本地4square,但基于RFID标签。

无论如何,每个签到都存储在MySQL表中,其中包含userID和签入时间作为DATETIME列。

现在,我想说明哪些用户在不同电台之间的登机时间最近。

说明:假设用户A在21:43:12签到,然后又在21:43:19签到。他在7秒内在车站之间移动。

数据库中有成千上万的签到,如何编写SQL来选择具有两个最接近的签到时间的用户?

6 个答案:

答案 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

应该这样做。如上所述,可能会有点滞后。