web-dev-qa-db-fra.com

TSQL est parti rejoindre et seulement la dernière ligne de droite

J'écris une requête SQL pour obtenir le post et seulement le dernier commentaire de ce post (s'il existe) . Mais je ne peux pas trouver un moyen de limiter seulement 1 ligne pour la colonne de droite dans la jointure gauche.

Voici un exemple de cette requête.

SELECT post.id, post.title,comment.id,comment.message
from post
left outer join comment
on post.id=comment.post_id

Si post a 3 commentaires, je reçois 3 lignes avec cette publication, mais je ne veux qu'une ligne avec le dernier commentaire (classé par date).

Quelqu'un peut-il m'aider avec cette requête?

31
barbarian
SELECT  post.id, post.title, comment.id, comment.message
FROM    post
OUTER APPLY
        (
        SELECT  TOP 1 *
        FROM    comment с
        WHERE   c.post_id = post.id
        ORDER BY
                date DESC
        ) comment

ou

SELECT  *
FROM    (
        SELECT  post.id, post.title, comment.id, comment.message,
                ROW_NUMBER() OVER (PARTITION BY post.id ORDER BY comment.date DESC) AS rn
        FROM    post
        LEFT JOIN
                comment
        ON      comment.post_id = post.id
        ) q
WHERE   rn = 1

Le premier est plus efficace pour quelques articles avec de nombreux commentaires dans chacun; ce dernier est plus efficace pour de nombreux messages contenant peu de commentaires.

51
Quassnoi

Sous-requête:

SELECT p.id, p.title, c.id, c.message
FROM post p
LEFT join comment c
ON c.post_id = p.id AND c.id = 
                 (SELECT MAX(c.id) FROM comment c2 WHERE c2.post_id = p.id)
14
AGoodDisplayName

Vous voudrez vous joindre à une sous-requête qui renvoie le dernier commentaire de la publication. Par exemple:

select post.id, post.title. lastpostid, lastcommentmessage
from post
inner join
(
    select post.id as lastpostid, max(comment.id) as lastcommentmessage
    from post
    inner join comment on commment.post_id = post.id
    group by post.id
) lastcomment
    on lastpostid = post.id
3
Paul Williams

Couple d'options ....

Une façon est de faire le JOIN sur:

SELECT TOP 1 comment.message FROM comment ORDER BY comment.id DESC

(notez que je suppose que comment.id est un champ d'identité)

1
Ian Jacobs

quelle version de SQL Server? Si vous disposez de la fonction Row_Number (), vous pouvez trier vos commentaires selon le mot "premier", puis ajouter une clause "where RN = 1". Je n'ai pas d'exemple pratique ou de bonne syntaxe, mais j'ai des tonnes de requêtes qui font exactement cela. D'autres postes sont tous parmi les 1 000 façons dont vous pourriez le faire.

Je dirais le profil et voir celui qui fonctionne le mieux pour vous.

1
No Refunds No Returns

Vous n’avez pas dit le nom spécifique de votre champ de date, alors j’ai complété avec [DateCreated]. Ceci est essentiellement identique à la publication ci-dessus de AGoodDisplayName, mais en utilisant le champ de date au lieu de s'appuyer sur l'ordre de la colonne ID.

SELECT post.id, post.title, comment.id, comment.message
FROM post p
LEFT OUTER JOIN comment
ON comment.id = (
    SELECT TOP 1 id
    FROM comment
    WHERE p.id = post_id
    ORDER BY [DateCreated] ASC
)
0
Andy Raddatz