2011-04-17 6 views
1

J'ai un journal pour les documents qui passent par mon application. Le journal ressemble à ceci:SQL: comment obtenir les derniers articles?

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

je besoin d'une liste des document_id qui ont été « coincés » dans un certain status_code pour une durée donnée (disons 10 minutes, timestamp est timestamp Unix, BTW). Si un document_id particulier est "coincé" dans un certain status_code, ce status_code sera le dernier status_code pour ce document_id.

Comment puis-je demander cela? Les 2 choses que je ne suis pas sûr:

  1. Comment puis-je vérifier si le document a été dans un certain état pendant une certaine période de temps? Je suppose que je peux utiliser une sorte de fonction/formule dans mon SQL (par exemple now - 10 minutes), mais je ne sais pas comment faire cela.
  2. Comment vérifier la durée du dernier code d'état?
+1

À quoi sert RDBMS? (Bien que je devine MySQL est très probable de vos questions précédentes) –

+0

log_id pour le journal de table est le même pour deux lignes différentes - vraiment ?? – Hogan

+0

@martin - oui, MySQL – StackOverflowNewbie

Répondre

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

Je reçois une 'Colonne' document_id 'dans la liste des champs est ambiguë – StackOverflowNewbie

+0

@StackOverflowNewbie. Changez la première sélection en 'SELECT log.document_id'. –

+0

@Juan: thnx, corrigé. @Stack: durée ajoutée –

0

Pour votre pas. un et non. deux questions, voici ma proposition pour (je suppose que vous utilisez 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); 

D'accord, ce qui est happing là. Nous regroupons les lignes par document_id, et nous ordonnons les codes d'état et les horodatages dans GROUP_CONCAT pour obtenir la dernière entrée et la dernière avant-dernière.

Si votre code d'état peut avoir plus de 5 chiffres, puis remplacez RPAD (status_code, X), où X est le nombre maximal de longueur de status_code

60 * 10 - est à 10 minutes

last_status EN (100,200) - codes d'état Vous voulez obtenir seulement.

+0

L'OP écrit: "* Si un document_id particulier est" bloqué "dans un certain status_code, ce status_code sera le dernier status_code pour ce document_id *". Vous n'avez pas à vérifier la pré-dernière entrée, seulement la dernière. –

+0

si mon code de statut est en effet des entiers, je ne pense pas que la solution doive le supposer. Je pense qu'il suffit de trouver le dernier code d'état de ce document. – StackOverflowNewbie

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 
Questions connexes