Question de requête SQL: X a plusieurs Y. Obtenez tous les X et obtenez uniquement le plus récent Y par X
Question
Supposons que nous ayons deux tables. Publier et commenter. Le post a beaucoup de commentaires. Imaginez qu'ils soient quelque peu remplis, de sorte que le nombre de commentaires par publication varie. Je souhaite une requête qui saisira tous les articles, mais uniquement le dernier commentaire par article.
J'ai été dirigé vers les jointures et les sous-requêtes, mais je n'arrive pas à le comprendre.
Exemple de sortie:
Post1: Comment4 (le plus récent pour post1)
Post2: Comment2 (le plus récent pour post2)
Post3: Commentaire 10 (le plus récent pour post3)
etc ...
Toute aide serait grandement appréciée. Merci.
La solution
Cette réponse suppose que vous avez un identifiant unique pour chaque commentaire et qu'il s'agit d'un nombre croissant. C'est-à-dire que les messages postérieurs ont des nombres plus élevés que les messages précédents Ne doit pas nécessairement être séquentiel, il doit simplement correspondre à l'ordre d'entrée.
Commencez par créer une requête qui extrait l'identifiant de commentaire maximal, groupé par identifiant de publication.
Quelque chose comme ça:
SELECT MAX(ID) MaxCommentID, PostID
FROM Comments
GROUP BY PostID
Ceci vous donnera une liste d'identifiants de publication et l'identifiant de commentaire le plus élevé (le plus récent) pour chacun d'entre eux.
Ensuite, vous vous associez à ceci pour extraire le reste des données des commentaires, pour ces identifiants.
SELECT C1.*, C2.PostID
FROM Comments AS C1
INNER JOIN (
SELECT MAX(ID) MaxCommentID, PostID
FROM Comments
GROUP BY PostID
) AS C2 ON C1.CommentID = C2.MaxCommentID
Ensuite, vous vous joignez aux publications pour obtenir des informations sur ces publications.
SELECT C1.*, P.*
FROM Comments AS C1
INNER JOIN (
SELECT MAX(ID) MaxCommentID, PostID
FROM Comments
GROUP BY PostID
) AS C2 ON C1.CommentID = C2.MaxCommentID
INNER JOIN Posts AS P ON C2.PostID = P.ID
Une autre approche n’utilise pas du tout l’identifiant PostID de la requête interne. Tout d’abord, choisissez l’identifiant de commentaire maximal pour tous les articles uniques, mais ne vous souciez pas de quel article, nous savons qu'ils sont uniques.
SELECT MAX(ID) AS MaxCommentID
FROM Comments
GROUP BY PostID
Ensuite, faites une clause IN pour obtenir le reste des données pour ces commentaires:
SELECT C1.*
FROM Comments
WHERE C1.ID IN (
SELECT MAX(ID) AS MaxCommentID
FROM Comments
GROUP BY PostID
)
Ensuite, rejoignez simplement les messages:
SELECT C1.*, P.*
FROM Comments AS C1
INNER JOIN Posts AS P ON C1.PostID = P.ID
WHERE C1.ID IN (
SELECT MAX(ID) AS MaxCommentID
FROM Comments
GROUP BY PostID
)
Autres conseils
Sélectionnez le commentaire le plus récent dans une sous-requête
exemple
Select *
from Posts po
Inner Join
(
Select CommentThread, CommentDate, CommentBody, Post from comments a
inner join
(select commentthread, max(commentdate)
from comments b
group by commentthread)
on a.commentthread = b.commentthread
and a.commentdate = b.commentdate
) co
on po.Post = co.post
select *
from post
, comments
where post.post_id = comments.post_id
and comments.comments_id = (select max(z.comments_id) from comments z where z.post_id = post.post_id)
Et si vous êtes toujours bloqué avec une ancienne version de MySQL, qui ne connaît pas les sous-requêtes, vous pouvez utiliser quelque chose comme
SELECT p.id, c1.id FROM posts as p LEFT JOIN comments as c1 ON p.id = c1.postId LEFT JOIN comments as c2 ON c1.postId = c2.postId AND c1.id < c2.id WHERE isnull(c2.id) ORDER BY p.idDans tous les cas, vérifiez votre requête avec EXPLAIN pour les problèmes de performances.