這是一個時間序列問題。在這個lockactivity表中你有一系列擊鍵(與其他東西混合)。我們需要將擊鍵分成彼此相鄰的組。
此查詢(http://sqlfiddle.com/#!2/6ffed/21/0)這樣做。爲了完整起見,我要離開*
擊鍵。
SELECT TIMESTAMPDIFF(SECOND, @prevVal, req_time) AS timediff,
@prevVal := req_time AS req_time,
lockip, keyvalue
FROM lockactivity,
(SELECT @prevVal := MIN(req_time) -
INTERVAL 1 HOUR FROM lockactivity) AS r
WHERE LENGTH(keyvalue) = 1
ORDER BY lockip, id
結果集的前幾行是這樣的:
TIMEDIFF REQ_TIME LOCKIP KEYVALUE
3604 2014-02-27 09:29:55 192.168.1.49 3
0 2014-02-27 09:29:55 192.168.1.49 6
1 2014-02-27 09:29:56 192.168.1.49 4
0 2014-02-27 09:29:56 192.168.1.49 1
0 2014-02-27 09:29:56 192.168.1.49 *
1155 2014-02-27 09:49:11 192.168.1.49 3
見按鍵的每一個新的「一堆」如何與一個比較大的timeDiff測量開始?
我們的下一步是創建一個計劃,在每串按鍵上添加一個新的序列號。這個討厭的查詢(http://sqlfiddle.com/#!2/6ffed/25/0)這樣做。
SELECT TIMESTAMPDIFF(SECOND, @prevVal, req_time) AS timediff,
IF(ABS(TIMESTAMPDIFF(SECOND, @prevVal, req_time))> 120,
@seq:[email protected]+1,
@seq) AS seq,
@prevVal := req_time AS req_time,
lockip, keyvalue
FROM lockactivity,
(SELECT @prevVal := MIN(req_time) -
INTERVAL 1 HOUR FROM lockactivity) AS r,
(SELECT @seq := 0) AS s
WHERE LENGTH(keyvalue) = 1
ORDER BY lockip, id
注意上面的120
。我任意選擇將具有120秒或更少的延遲的擊鍵羣集起來。您可能需要選擇不同的羣集編號。還要注意,當我們獲得第二個ip時,timediff向後跳,所以我使用ABS()
作爲聚類準則。
最後,我們需要用GROUP_CONCAT等來總結這個東西。這個查詢(http://sqlfiddle.com/#!2/6ffed/28/0)這樣做。
SELECT lockip,
GROUP_CONCAT(keyvalue
ORDER BY id
SEPARATOR '') AS keystrokes,
MAX(req_time) AS finish_time
FROM (
SELECT TIMESTAMPDIFF(SECOND, @prevVal, req_time) AS timediff,
IF(ABS(TIMESTAMPDIFF(SECOND, @prevVal, req_time))> 120,
@seq:[email protected]+1,
@seq) AS seq,
@prevVal := req_time AS req_time,
id, lockip, keyvalue
FROM lockactivity,
(SELECT @prevVal := MIN(req_time) -
INTERVAL 1 HOUR FROM lockactivity) AS r,
(SELECT @seq := 0) AS s
WHERE LENGTH(keyvalue) = 1
ORDER BY lockip, id
) AS seq
GROUP BY seq, lockip
ORDER BY MAX(req_time)
下面是結果集,它看起來正是你所需要的。我不完全確定最後兩個關鍵序列。您可能需要擺弄集羣時間才能正確使用這些東西。
LOCKIP KEYSTROKES FINISH_TIME
192.168.1.49 3641* 2014-02-27 09:29:56
192.168.1.49 3 2014-02-27 09:49:11
192.168.1.49 3641* 2014-02-27 20:29:49
192.168.1.49 3641* 2014-02-27 20:33:32
192.168.1.55 1122* 2014-02-27 21:06:42
192.168.1.55 1122** 2014-02-27 21:45:52
192.168.1.55 1122* 2014-02-27 22:12:38
192.168.1.49 3641*11015* 2014-02-27 22:13:11
192.168.1.49 33015*11015* 2014-02-27 22:20:10
最後,OP對查詢進行了一些進一步調整,以拆分星號分隔的序列。
jinxjy更新:根據我的評論,我對上面的最後一個查詢做了一些小的修改,除了之前創建的時間戳序列之外,還使用*作爲分隔符。其他小編輯包括將120更改爲6,因爲這是鍵盤上的標準按鍵超時,並將*隱藏在最終代碼列中。這也被髮布到sqlfiddle(http://sqlfiddle.com/#!2/6ffed/53/0)
SELECT lockip,
GROUP_CONCAT(keyvalue
ORDER BY id
SEPARATOR '') AS code,
MAX(req_time) AS finish_time
FROM (
SELECT TIMESTAMPDIFF(SECOND, @prevVal, req_time) AS timediff,
IF(keyvalue="*",
@flag:=1,
@flag:=0) AS flag,
IF(ABS(TIMESTAMPDIFF(SECOND, @prevVal, req_time))> 6,
@seq:[email protected][email protected],
@seq:[email protected][email protected]) AS seq,
@prevVal := req_time AS req_time,
id, lockip, keyvalue
FROM lockactivity,
(SELECT @prevVal := MIN(req_time) - INTERVAL 1 HOUR FROM lockactivity) AS r,
(SELECT @seq := 0) AS s,
(SELECT @flag:= 0) AS n
WHERE LENGTH(keyvalue) = 1
ORDER BY lockip, id
) AS seq
WHERE flag=0
GROUP BY seq, lockip
ORDER BY MAX(req_time) DESC
這給了我理想的結果:
| LOCKIP | CODE | FINISH_TIME |
|--------------|-------|---------------------|
| 192.168.1.49 | 11015 | 2014-02-27 22:20:10 |
| 192.168.1.49 | 33015 | 2014-02-27 22:20:04 |
| 192.168.1.49 | 11015 | 2014-02-27 22:13:11 |
| 192.168.1.49 | 3641 | 2014-02-27 22:13:06 |
| 192.168.1.55 | 1122 | 2014-02-27 22:12:38 |
| 192.168.1.55 | 1122 | 2014-02-27 21:45:48 |
| 192.168.1.55 | 1122 | 2014-02-27 21:06:41 |
| 192.168.1.49 | 3641 | 2014-02-27 20:33:32 |
| 192.168.1.49 | 3641 | 2014-02-27 20:29:48 |
| 192.168.1.49 | 3 | 2014-02-27 09:49:11 |
| 192.168.1.49 | 3641 | 2014-02-27 09:29:56 |
有趣的問題!
儘管有辦法從表格中獲取安全代碼,但我認爲當表格變大時它們會很貴。我不禁想到合併鍵擊應該由代碼從鍵盤獲取事件並將其存儲到數據庫中,而不是存儲每個原始鍵擊。 – Barmar
歡迎來到SO。感謝仔細思考的問題。它看起來像有一個按鍵的時間序列,而且不同的代碼以大於幾秒的時間分隔。 –
@Barmar:這幾乎花了我幾個月的時間才能得到原始的按鍵!這些按鍵發送的小鍵盤的自動化能力非常有限,所以我的選擇是通過數據庫處理這些數據,或者構建一個Web服務,在通往數據庫的途中陷入並構建代碼。如果目前的方法長期存在任何問題,我將調查Web服務的可能性。感謝您的迴應。 – jinxjy