我正在構建一個基於位置的檢查插件的Web應用程序,有點像本地4square,但基於RFID標籤。如何找到哪兩行的時間戳彼此最接近?
無論如何,每個檢入存儲在MySQL表與用戶ID和檢測在作爲DATETIME列的時間。
現在我想顯示哪些用戶有不同站之間的最近登記時間。
說明:假設用戶A在21時43分12秒再次在21時43分19秒簽入,然後。他在7秒之內在車站之間移動。
有成千上萬簽入的數據庫,我怎麼寫SQL選擇有兩個最接近的入住時間的用戶?
我正在構建一個基於位置的檢查插件的Web應用程序,有點像本地4square,但基於RFID標籤。如何找到哪兩行的時間戳彼此最接近?
無論如何,每個檢入存儲在MySQL表與用戶ID和檢測在作爲DATETIME列的時間。
現在我想顯示哪些用戶有不同站之間的最近登記時間。
說明:假設用戶A在21時43分12秒再次在21時43分19秒簽入,然後。他在7秒之內在車站之間移動。
有成千上萬簽入的數據庫,我怎麼寫SQL選擇有兩個最接近的入住時間的用戶?
真快解決方案會引入一些預先計算。就像存儲當前和前一次簽入之間的差異一樣。
在這種情況下,你會選擇在快速的方式需要什麼(只要你涵蓋索引列)。
不使用在這種情況下,預先計算將導致這將在笛卡爾式生產經營可怕查詢。
我想我可以計算和存儲每個用戶的簽入與每一行之間的時差。你是這個意思嗎? – 2012-08-03 12:41:24
嘿夥計,你能幫我一個忙,看看這[問題](http://stackoverflow.com/questions/11790402/pdo-refuses-to-delete-a-row-of-data-in-具體表)我的?它讓我難倒了一個混蛋: – Fluffeh 2012-08-03 12:41:32
@MånsJonasson。不是真的,你只需計算相同用戶標識的後續**簽入之間的差異,這意味着你會在簽入表中添加一個新列:'差異' 。每次插入新簽入時,都會選擇最後一次簽入相同的用戶標識,並計算與最後一次簽入的數據差異。 – bpgergo 2012-08-03 14:30:21
你有什麼試過?你看DATEDIFF http://msdn.microsoft.com/en-us/library/ms189794.aspx
乾杯 --Jocke
試試這個:
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
爲每個用戶做一個交叉產品的確會非常糟糕。這與使用相關的子查詢相比如何? – MatBailie 2012-08-03 12:28:39
'abs(a.rfid-b.rfid)'只要兩列不參與'group by'並且沒有聚合函數,就會返回不可預知的結果 – zerkms 2012-08-03 12:28:45
謝謝,翻譯成我的行名,它看起來像這樣: 選擇 \t a.id, \t b.id, a.uid, b.uid, ABS(a.dateWhen-b.dateWhen) 從 rfid_actions一個, rfid_actions b 其中 一個。 uid = b.uid group by a.uid, b.uid order by 級ABS(a.dateWhen-b.dateWhen)遞減 限1 但結果很奇怪: 的ID(2)UID UID(2)ABS(a.date ... 6a42c540 \t 6a42c540 \t 0.000000 (當然,我還沒有得到stackoverflow降價) – 2012-08-03 12:32:07
首先,您需要用戶的索引,然後是時間戳。
其次,您需要使用相關的子查詢來查找「下一個時間戳」。
然後使用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()
的結果。每次記錄新的簽入時,也計算並存儲自上次簽入以來的持續時間,可能使用觸發器。通過預先計算,查詢變得更簡單,值可索引。
我的身影,你只需要計算兩個簽入之間的區別,如果他們是同一個人的兩個連續簽入。
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;
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
應該這樣做。如上所述可能有點遲緩。
對於*快速*查找,您需要預先計算時間以便以前簽入並將其存儲在某個地方 – zerkms 2012-08-03 12:26:27
您只需要用戶ID?或者你還想要相關的時間戳嗎? – MatBailie 2012-08-03 12:34:50