【问题标题】:How do I join to the latest record in the table?如何加入表中的最新记录?
【发布时间】:2010-10-27 05:48:38
【问题描述】:

我需要做的很简单……但现在是凌晨 3 点,我可能忽略了显而易见的事情。

我正在编写一个简单的论坛。一个表存储论坛标题、描述等,而另一个存储帖子。在论坛列表中,显示所有论坛的列表,我想抓取每个论坛中的最新帖子,并显示帖子主题、发布者和帖子 ID 和日期。很简单。

唯一的问题是,当我加入帖子表时,它会加入表中的第一个记录,而不是最后一个记录,这表示该论坛中的最后一个帖子。

这是获取“最新”帖子(现在用作“第一篇帖子”)的论坛列表和数据的简化查询。

SELECT forum_title, forum_id, post_subject, post_user, post_id, post_date FROM board_forums 
     LEFT JOIN board_posts 
     ON (forum_id = post_parentforum AND post_parentpost = 0) 
WHERE forum_status = 1
GROUP BY forum_id
ORDER BY forum_position

我该如何解决这个问题?

【问题讨论】:

    标签: php mysql greatest-n-per-group


    【解决方案1】:

    您遇到的问题是经典的Ambiguous GROUP BY 问题。这是 MySQL 特有的,因为其他 RDBMS(和标准 SQL)根本不允许您的查询。您的查询未通过单值规则,因为您没有在 GROUP BY 中列出所有非聚合列。

    这是一个解决方案,展示了我最喜欢的每组获得最大行数的方法:

    SELECT f.forum_title, f.forum_id, p1.post_subject, p1.post_user, 
      p1.post_id, p1.post_date 
    FROM board_forums f
    LEFT JOIN board_posts p1
      ON (f.forum_id = p1.post_parentforum AND p1.post_parentpost = 0)
    LEFT JOIN board_posts p2
      ON (f.forum_id = p2.post_parentforum AND p2.post_parentpost = 0 
          AND p1.post_id < p2.post_id)
    WHERE p2.post_id IS NULL AND f.forum_status = 1
    ORDER BY f.forum_position;
    

    如果p2.post_id IS NULL,则意味着在p2 中找不到帖子,这大于在p1 中找到的帖子。

    所以,p1 是最新的帖子(假设 post_id 是自动递增的)。


    重新评论:

    这个有点问题。 ID 最高的 post_id 不一定是最新的帖子。

    没问题。只需使用保证区分较早帖子和较晚帖子的列。你提到post_date。在平局的情况下,您必须打破与另一列(或多列)的平局,这肯定是按时间顺序排列的。

    LEFT JOIN board_posts p2
      ON (f.forum_id = p2.post_parentforum AND p2.post_parentpost = 0 
        AND (p1.post_date < p2.post_date 
          OR p1.post_date = p2.post_date AND p1.post_millisecond < p2.post_millisecond))
    

    【讨论】:

    • 我很高兴你提到了这个问题 - 我回到这个问题六次,但甚至无法弄清楚查询是如何工作的,因为它写在那里,所以放弃了.不是 MySQL 用户,我没有意识到它会让你在不修复 GROUP BY 的情况下滑动。现在我明白了! :)
    • 是的。 MySQL 相信您知道自己在做什么,并且您遵循单值规则。 SQLite 也有同样的行为。如果您编写的查询具有不明确的列(每组多个值),RDBMS 会任意选择一个值。 MySQL 从“第一”行中选择值(按照行的物理存储顺序)。巧合的是,SQLite 从“最后”行中选择值。
    • 这个有点问题。 ID 最高的 post_id 不一定是最新的帖子。如果创建了一个新线程,它将具有最新的 ID,在这种情况下,您的示例有效。但是,一旦在较旧的线程(具有较低的 id)上做出回复,它就不再像它应该的那样运行,并且仍然显示具有最高 ID 的 therad。它需要根据 post_date 显示它。
    • 谢谢比尔。你是救生员!
    猜你喜欢
    • 2011-03-07
    • 2012-01-06
    • 1970-01-01
    • 2020-11-07
    • 2016-03-15
    • 2021-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多