【问题标题】:TSQL left join and only last row from rightTSQL 左连接,只有右起最后一行
【发布时间】:2011-01-17 21:38:38
【问题描述】:

我正在编写 sql 查询来获取帖子,并且只有该帖子的最后一条评论(如果存在)。 但我无法找到一种方法来限制左连接中右列仅 1 行。

这是此查询的示例。

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

如果帖子有 3 个 cmets,我会得到 3 行这个帖子,但我只想要 1 行最后评论(按日期排序)。

有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: sql sql-server tsql left-join


    【解决方案1】:
    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
    

    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
    

    前者对于每个帖子中有很多 cmets 的帖子效率更高;后者对于许多帖子中只有很少的 cmets 更有效。

    【讨论】:

    • 感谢您的回答。我使用下一个代码。 SELECT post.id, post.title,c.id as comment_id,c.message from post left outer join (select comment.id,comment.post_id,comment.message, ROW_NUMBER() OVER (PARTITION BY comment.post_id ORDER BY comment .date DESC) AS rn from comment) c on post.id=c.post_id where c.rn=1 or c.rn is null
    • APPLY 运算符为我解决了这个问题。我正在进行一对多连接,但需要将右侧匹配减少到仅最近创建的匹配。谢谢!
    • 将这两个放在一起显示估计的查询计划很有趣,apply 选项是查询成本的 99% :o
    • @FelipeSabino:如果您在大象笼子上看到“水牛”标志,请不要相信自己的眼睛。
    【解决方案2】:

    子查询:

    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)
    

    【讨论】:

    • 如果我没有遗漏什么,这应该比我的执行计划所接受的答案快得多(比如 10 倍)。
    • 对我来说,这似乎比在接受的答案中使用庞大的子查询更有效。 stackoverflow.com/questions/4692419/… 中有相关的答案。它在子查询中使用 TOP 1/ORDER BY 解决方案而不是 MAX。
    • 我相信这是更简短更好的答案。
    • 这将在按 ID 排序时返回最后一条评论,而不是按 OP 要求的日期排序
    【解决方案3】:

    您需要加入一个返回帖子最后评论的子查询。例如:

    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
    

    【讨论】:

      【解决方案4】:

      几个选项....

      一种方法是在以下位置进行 JOIN:

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

      (注意我假设 comment.id 是一个身份字段)

      【讨论】:

      • 如果Identity字段有负增量怎么办?
      • 你遇到过这样的事情吗?
      【解决方案5】:

      什么版本的 SQL Server?如果您有可用的 Row_Number() 函数,您可以按照“first”对您的任何含义对 cme​​ts 进行排序,然后添加“where RN=1”子句。在我的脑海中没有一个方便的示例或正确的语法,但确实有大量的查询可以做到这一点。其他帖子都是你可以做到这一点的 1000 种方式。

      我会说它,看看哪一个最适合你。

      【讨论】:

        【解决方案6】:

        你没有说你的日期字段的具体名称,所以我填写了[DateCreated]。这与上面 AGoodDisplayName 的帖子基本相同,但使用日期字段而不是依赖 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
        )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-04-27
          • 1970-01-01
          • 1970-01-01
          • 2015-06-03
          • 2012-12-21
          • 2021-01-05
          • 2020-01-08
          相关资源
          最近更新 更多