3

私はロケーションベースのチェックイン用のWebアプリケーションを構築しています。これは、ローカルの4squareのようなものですが、RFIDタグに基づいています。

とにかく、各チェックインは、userIDとチェックインの時刻をDATETIME列としてMySQLテーブルに格納されます。

次に、異なるステーション間で最も近いチェックイン時間を持っているユーザーを示したいと思います。

説明:ユーザーAが21:43:12にチェックインし、次に21:43:19にチェックインしたとします。彼は7秒で駅間を移動しました。

データベースには何千ものチェックインがありますが、2つの最も近いチェックイン時間を持つユーザーを選択するSQLを作成するにはどうすればよいですか?

4

6 に答える 6

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 に答える
1

本当に速い解決策は、いくつかの事前計算を導入します。現在のチェックインと以前のチェックインの違いを保存するようなものです。

この場合、必要なものをすばやく選択します(その列をインデックスでカバーしている限り)。

この場合に事前計算を使用しないと、デカルトのようなプロダクションで動作するひどいクエリが発生します。

于 2012-08-03T12:31:17.453 に答える
0

何を試しましたか?DATEDIFFhttp://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一時テーブルに保存してから、そのテーブルで最小期間を共有するすべてのユーザーを検索することをお勧めします。


データの量によっては、これは遅くなる可能性があります。最適化の1つは、の結果をキャッシュすることTIMEDIFF()です。新しいチェックインが記録されるたびに、おそらくトリガーを使用して、最後のチェックインからの期間も計算して保存します。これを事前に計算しておくと、クエリが簡単になり、値にインデックスを付けることができます。

于 2012-08-03T12:42:24.253 に答える
0

同じ人物の2つの連続したチェックインである場合にのみ、2つのチェックインの差を計算したいと思います。

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
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 に答える