3

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

无论如何,每次签入都存储在一个 MySQL 表中,其中包含一个用户 ID 和签入时间作为 DATETIME 列。

现在我想显示哪些用户在不同车站之间的签到时间最近。

解释:假设用户 A 在 21:43:12 签到,然后在 21:43:19 签到。他在 7 秒内移动了两个站点。

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

4

6 回答 6

1

真正快速的解决方案会引入一些预先计算。就像存储当前和以前签入之间的差异一样。

在这种情况下,您可以快速选择所需的内容(只要您按索引覆盖该列)。

在这种情况下不使用预计算会导致可怕的查询,这些查询将在类似笛卡尔的产品上运行。

于 2012-08-03T12:31:17.453 回答
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
于 2012-08-03T12:27:00.957 回答
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;
于 2012-08-03T12:45:28.900 回答
0

你试过什么?你看过 DATEDIFF http://msdn.microsoft.com/en-us/library/ms189794.aspx

干杯——乔克

于 2012-08-03T12:26:49.380 回答
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(). 每次记录新签入时,还要计算并存储自上次签入以来的持续时间,可能使用触发器。预先计算此值可使查询更简单且值可索引。

于 2012-08-03T12:42:24.253 回答
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

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

于 2012-08-03T13:12:50.477 回答