2011-04-17 56 views
1

我有一個日誌文件,通過我的應用程序。日誌看起來是這樣的:SQL:如何獲取最後的項目?

TABLE: log 
================================================== 
| log_id | document_id | status_code | timestamp | 
================================================== 
| 1  | 10   | 100   | 12345  | 
-------------------------------------------------- 
| 2  | 10   | 200   | 23456  | 
-------------------------------------------------- 

我需要一直「卡」在一定status_code給定的時間的document_id列表(比方說10分鐘; timestamp是Unix時間戳,順便說一句)。如果某個特定的document_id在某個status_code中「卡住」,則該status_code將是該document_id的最後status_code

我該如何查詢?我不確定的兩件事:

  1. 如何檢查文檔是否處於特定狀態一段時間?我猜我可以在我的SQL中使用某種函數/公式(例如now - 10分鐘),但我不知道該怎麼做。
  2. 如何檢查只有最後一個狀態碼的持續時間?
+1

這是什麼RDBMS? (儘管我猜「MySQL」很可能來自你以前的問題) – 2011-04-17 21:35:30

+0

log_id對於兩個不同行的表記錄是相同的 - 真的嗎? – Hogan 2011-04-17 21:40:58

+0

@martin - 是的,MySQL – StackOverflowNewbie 2011-04-17 21:42:17

回答

2
SELECT log.document_id 
    , (UNIX_TIMESTAMP() - log.timestamp)/60 
     AS MinutesSinceLastChange 
FROM log 
    JOIN 
    (SELECT document_id 
      , MAX(timestamp) AS last_change 
     FROM log 
     GROUP BY document_id 
     HAVING (last_change < (UNIX_TIMESTAMP() - 60 * 10)) <-- that is 10 minutes 
    ) AS grp 
    ON grp.document_id = log.document_id 
    AND grp.last_change = log.timestamp 
WHERE log.status_code = "200"    <-- code you want to check 
+0

我得到一個'欄'document_id'字段列表中不明確' – StackOverflowNewbie 2011-04-17 21:59:18

+0

@StackOverflowNewbie。將第一個選擇改爲「SELECT log.document_id」。 – 2011-04-17 22:03:31

+0

@Juan:thnx,糾正它。 @Stack:添加時間 – 2011-04-17 22:08:49

0

對於你的沒有。一個也沒有。兩個問題,這是我的主張(我猜你正在使用MySQL):

SELECT 
    `document_id`, 
    SUBSTR(GROUP_CONCAT(RPAD(`status_code`,5) ORDER BY `timestamp` DESC), 1, 5) AS `last_status`, 
    SUBSTR(GROUP_CONCAT(RPAD(`status_code`,5) ORDER BY `timestamp` DESC), 7, 5) AS `prev_status`, 

    UNIX_TIMESTAMP(SUBSTR(GROUP_CONCAT(FROM_UNIXTIME(`timestamp`) ORDER BY `timestamp` DESC), 1, 19)) AS `last_timestamp`, 
    UNIX_TIMESTAMP(SUBSTR(GROUP_CONCAT(FROM_UNIXTIME(`timestamp`) ORDER BY `timestamp` DESC), 21, 19)) AS `prev_timestamp` 
FROM `log` 
GROUP BY `document_id` 
HAVING `last_timestamp` - `prev_timestamp` > 60*10 AND `last_status` IN (100,200); 

好的,什麼是在那裏。我們按照document_id對行進行分組,並在GROUP_CONCAT中訂購狀態代碼和時間戳以獲取最後和最後一個條目。

如果你的狀態碼可以具有多於5個數字,則更換它RPAD(status_code,X),其中X是STATUS_CODE長度的最大數目

60 * 10 - 10分鐘

last_status IN (100,200) - 狀態代碼您只想獲取。

+0

OP寫道:「*如果特定的document_id在特定的status_code中」卡住「,則該status_code將是該document_id *的最後一個status_code。您不必檢查前最後一項,只能檢查最後一項。 – 2011-04-17 22:02:09

+0

儘管我的狀態碼確實是整數,但我不認爲解決方案需要假設。我認爲它只需要找到該文件的最後一個狀態碼。 – StackOverflowNewbie 2011-04-17 22:06:09

0
SELECT log.document_id, log.status_code, max(log.timestamp) - min(log.timestamp) 
FROM ( 
    SELECT MAX(log_id) as log_id 
    FROM log 
    GROUP BY document_id) latestLog 
    INNER JOIN log latestStatus ON latestStatus.log_id = latestLog.log_id 
    INNER JOIN log on latestStatus.status_code = log.status_code 
GROUP BY log.document_id, log.status_code 
HAVING (max(log.timestamp) - min(log.timestamp)) > 600