Reputation: 40643
I have a log for documents that go through my application. The log looks like this:
TABLE: log
==================================================
| log_id | document_id | status_code | timestamp |
==================================================
| 1 | 10 | 100 | 12345 |
--------------------------------------------------
| 2 | 10 | 200 | 23456 |
--------------------------------------------------
I need a list of document_id
that have been "stuck" in a certain status_code
for a given duration (say 10 minutes; timestamp
is Unix timestamp, btw). If a particular document_id
is "stuck" in a certain status_code
, that status_code
will be the last status_code
for that document_id
.
How do I query this? The 2 things I'm not sure of:
now
- 10 minutes), but I don't know how to do that.Upvotes: 1
Views: 348
Reputation: 1545
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
Upvotes: 0
Reputation: 115560
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
Upvotes: 2
Reputation: 1663
For Your no. one and no. two question, this is my proposition for (I guess You are using 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);
All right, what is happing there. We're grouping rows by document_id, and ordering status codes and timestamps inside GROUP_CONCAT to get the last and pre-last entry.
If Your status code can have more than 5 digits, then replace it RPAD(status_code
,X), where X is maximal number of status_code length
60*10 - is 10 minutes
last_status
IN (100,200) - status codes You want to get only.
Upvotes: 0