2012-06-15 5 views
1

J'essaye de trouver les dernières entrées de journal dans ma base de données MySQL. J'ai préparé cette requête tard dans la nuit, mais lors des tests d'aujourd'hui, il ne semble pas que je retourne les bonnes données. La requête s'exécute très bien, mais aucun des autres champs ne semble correspondre à la colonne d'id. Il saisit le nombre d'ID max, mais hostName, email et info ne correspondent pas à l'ID, et ils ne sont pas les derniers. J'ai passé quelques heures à faire tourner mes roues (je suis un Noob MySQL et je fais juste ça pour m'amuser) donc je suis assez confus maintenant ..Pourquoi la requête mysql renvoie-t-elle un mauvais résultat?

Merci pour toute aide!

EDIT: Wow merci pour toutes les réponses! Désolé pour la confusion, j'aurais dû dire "Je veux le dernier journal par nom d'hôte!" < - C'est précisément ce dont j'ai besoin.

+0

Pourquoi avez-vous besoin du MAX()? La commande par heure n'est-elle pas suffisante pour obtenir les dernières entrées du journal? –

+0

Hmm .. je viens de l'enlever et j'obtiens des données qui ont presque 30 minutes. – David

+0

Pouvez-vous expliquer le résultat que vous voulez? "Seule la dernière entrée de chaque hôte et ID"? – Akarun

Répondre

1

Une autre façon de faire la même chose est à GROUP BY puis JOIN à la table du journal:

Si "dernier" signifie que le maximum id, utilisez un index (hostname, time, id) et ceci:

SELECT log.id 
FROM 
     log 
    JOIN 
     (SELECT MAX(id) AS id 
      FROM log 
      WHERE time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) 
      GROUP BY hostName 
     ) AS grp 
     ON grp.id = log.id ; 

MISE À JOUR: Vous pouvez également vouloir essayer celui-ci. Il pourrait être plus efficace (en fonction de la distribution de nom d'hôte) - et bénéficierait d'un indice: indice (hostname, id, time):

SELECT log.id 
FROM 
     log 
    JOIN 
     (SELECT MAX(id) AS id 
      FROM log 
      GROUP BY hostName 
     ) AS grp 
     ON grp.id = log.id 
WHERE log.time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) ; 

Si « dernier » signifie le maximum time (par exemplesi time est insertion_time et n'est pas changé par la suite), utilisez un index (hostname, time) et ceci:

SELECT log.* 
FROM 
     log 
    JOIN 
     (SELECT hostname, MAX(time) AS max_time 
      FROM log 
      WHERE time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) 
      GROUP BY hostname 
     ) AS grp 
     ON grp.hostname = log.hostname 
     AND grp.max_time = log.time ; 

Et enfin, puisque tout le monde a oublié de répondre aux « Pourquoi requête MySQL est faux retour Résultats? » question, voici une autre question avec quelques réponses utiles: Why does MySQL add a feature that conflicts with SQL standards?

+0

Merci, je crois que j'ai un index sur id car c'est la clé primaire. Je cherche à en ajouter un sur le nom d'hôte maintenant! :) – David

+1

Pas sur '(nom d'hôte)' mais sur '(nom d'hôte, id)' –

+0

Hm, je n'ai pas pensé à la condition 'time'. Cela ne va pas être facile. –

0

Ceci est un célèbre:

SELECT * 
FROM log 
WHERE log.id IN (
    SELECT MAX(id) 
    FROM log 
    WHERE time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) 
    GROUP BY hostName) T 
1

Si vous voulez que la ligne complète qui correspond à l'ID max pour chaque hostName distinct,

SELECT id, hostName, email, info, time 
FROM log 
WHERE id IN 
    (SELECT MAX(id) FROM log WHERE time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) 
    GROUP BY hostName) 
ORDER BY `time` DESC 
+0

Cette requête a pris 177 secondes pour s'exécuter O_O – David

+0

Avez-vous l'index utile sur hostName? –

+0

Négatif. J'ai entendu parler des index et je devrais vraiment commencer à les rechercher .. Je vais essayer d'en ajouter un. – David

2

Vous avez dit:

J'essaie de trouver les dernières entrées de journal dans ma base de données MySQL

Il n'est pas nécessaire de grouper ni d'utiliser une sous-requête. Essayez ceci:

SELECT id, hostName, email, info, time FROM log 
WHERE time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) 
ORDER BY `time` DESC 

Maintenant, vous avez dit:

Je veux que le dernier journal par nom d'hôte!

Ensuite, la solution doit être ceci:

SELECT l1.id, l1.hostName, l1.email, l1.info, l1.time FROM log l1 
LEFT JOIN log l2 on l1.hostName = l2.hostName AND l1.time < l2.time 
WHERE l2.time IS NULL 
ORDER BY l1.time DESC 
+0

Merci, mais je cherche spécifiquement un journal par nom d'hôte! – David

+0

Tout à fait une question différente! –

+0

Je sais, je ne suis pas bon à expliquer les choses que je ne connais pas bien * gêné * – David

Questions connexes