SQL:如何获取最后一项?

时间:2011-04-17 21:33:21

标签: mysql sql database

我有一份记录通过我的申请的文件。日志看起来像这样:

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

我需要一个document_id的列表,这些列表已在某个status_code中“卡住”一段时间(比如10分钟; timestamp是Unix时间戳,顺便说一句)。如果某个document_id中某个特定status_code被“卡住”,status_code将成为该status_code的最后document_id

我如何查询?我不确定的两件事:

  1. 如何检查文档是否在某段时间内处于特定状态?我猜我可以在我的SQL中使用某种函数/公式(例如now - 10分钟),但我不知道该怎么做。
  2. 如何检查最后一个状态代码的持续时间?

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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) - 状态代码您只想获取。

答案 2 :(得分: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