8 votes

Requête SQL - Combiner DISTINCT et TOP ?

J'ai la requête suivante que je veux lancer :

SELECT DISTINCT TOP(5) fp.PostId FROM dbForumPosts fp
LEFT JOIN dbForumEntry fe ON fp.PostId = fe.PostId
Order by fe.Datemade DESC

Cependant, lorsque je le lance, j'obtiens l'erreur suivante :

Msg 145, Level 15, State 1, Line 1
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.

J'ai essayé de modifier la requête pour qu'elle utilise GROUP BY à la place, mais j'ai alors le problème suivant :

Msg 8127, Level 16, State 1, Line 4
Column "dbForumEntry.Datemade" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.

CE QUE JE VEUX :

Considérez ceci comme un forum. Il y a des messages (dbForumPosts) et des entrées (dbForumEntry). Il y a 0-many entries pr post.

Ce que je veux, c'est obtenir les messages avec l'activité la plus récente (les messages avec les dernières entrées mises à jour).

6voto

Andomar Points 115404

Vous pourriez trouver le plus récent Datemade par PostId con row_number . Vous pouvez ensuite rechercher les 5 derniers messages :

select  top 5 PostId
from    (
        select  PostId
        ,       Datemade
        ,       row_number() over (partition by PostId
                    order by Datemade) as rn
        from    dbForumEntry
        ) SubQueryAlias
where   rn = 1 -- Most recent row per PostId
order by
        Datemade desc

Vous pouvez également obtenir le même résultat avec un fichier de type group by sous-requête :

select  top 5 PostId
from    (
        select  PostId
        ,       max(Datemade) as LastDate
        from    dbForumEntry
        group by
                PostId
        ) SubQueryAlias
order by
        LastDate desc

Si dbForumEntry a une colonne d'identification (disons ForumEntryId ), une requête comme celle-ci pourrait être plus performante. La base de données peut l'exécuter sans compiler le fichier row_number o max(Datemade) pour l'ensemble du tableau.

select  top 5 PostId
from    dbForumPosts fp
where   not exists -- No later entry for the same post exists
        (
        select  *
        from    dbForumPosts fp2
        where   fp2.PostId = fp.PostId
                and fp2.ForumEntryId > fp.ForumEntryId
        )
order by
        Datemade desc

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X