我有用戶操作表,每個用戶操作都有一個用戶關聯,一個類型和一個時間戳。這裏有一個簡化的例子:匹配來自MySQL表的用戶操作:每個CLOSE應該與給定用戶的前一個OPEN匹配
TABLE USER_ACTIONS
------------------------
USER | TYPE | TIMESTAMP
------------------------
a | OPEN | 0
b | OPEN | 1
a | CLOSE | 2
a | OPEN | 3
b | CLOSE | 4
a | CLOSE | 4
a | OPEN | 5 <-- "orphaned" OPEN, with no corresponding CLOSE. Should be ignored.
c | OPEN | 3
c | CLOSE | 5
a | OPEN | 6
a | CLOSE | 8
我想獲得一個交易時間列表。對於特定用戶,每個CLOSE應與之前的OPEN匹配。
我想會是這個樣子的結果:
USER | TRANSACTION_TIME
-----------------------
a | 2
b | 3
a | 1
c | 2
a | 2
我不關心排序。
我知道這可以通過編程來完成,但是有可能使用一些聰明的SQL嗎?
UPDATE:
以編程方式做到這一點,一般的想法是......
- 選擇所有的 「CLOSE」 行動,通過TIMESTAMP降序排列的。
- 對於列表中的每個人,嘗試查找由同一用戶進行的前一個「OPEN」操作。將TIMESTAMP限制在「CLOSE」動作TIMESTAMP之前,按TIMESTAMP DESC對結果進行排序,並將其限制爲1.
- 對於該對,計算時間差,並輸出結果。
下面是一些僞代碼,但實際上我想SQL,這是否巧妙:
for each CLOSE_ACTION IN ("SELECT USER, TYPE, TIMESTAMP FROM USER_ACTIONS WHERE TYPE='CLOSE' ORDER BY TIMESTAMP DESC;") {
OPEN_ACTION = "SELECT USER, TYPE, TIMESTAMP FROM USER_ACTIONS
WHERE TYPE='OPEN'
AND USER='<CLOSE_ACTION.USER>'
AND TIMESTAMP='<CLOSE_ACTION.TIMESTAMP>'
ORDER BY TIMESTAMP DESC
LIMIT 1";
if OPEN_ACTION != empty/null then {
print CLOSE_ACTION.USER, CLOSE_ACTION.TIMESTAMP - OPEN_ACTION.TIMESTAMP;
}
}
你知不知道你*總是*有一個OPEN關聯關聯?或者用戶可以打開,打開,關閉,打開,打開,關閉,關閉等等?如果數據不是*完全清潔*,你知道你想如何處理這種情況嗎? *(忽略重複打開,但將'CLOSE,CLOSE'視爲'CLOSE,OPEN,CLOSE',例如?)* – MatBailie 2012-01-11 16:24:56
好問題:不幸的是,每個OPEN都沒有CLOSE。我會更新我的表來反映這一點。對於這些情況,我只想讓孤兒的OPEN被忽略,而不是被計算在內。 – 2012-01-11 16:31:02
在你的例子中,如果模式是'OPEN,CLOSE,CLOSE',那麼應該忽略哪個關閉?我的答案目前忽略了第二個「CLOSE」,並符合你的描述的其餘部分。 – MatBailie 2012-01-11 16:49:19