左连接最后一条记录(简单的讨论区,主题,最后的帖子和用户)

时间:2014-07-24 15:27:06

标签: mysql subquery left-join ifnull groupwise-maximum

我正在尝试制作一个简单的讨论板,因此我需要与他们的作者和主题作者的主题标题最后的帖子。

到目前为止,我有这个

SELECT
    `t`.`id`,
    `t`.`title`,
    `t`.`date` as theme_date,
    `u`.`id` as user_id,
    `u`.`username` as user_username,
    COUNT(p.id) as count_posts,
    SUBSTRING_INDEX(GROUP_CONCAT(`p`.`id` ORDER BY `p`.`id` DESC SEPARATOR "| " ), "| ", 1) as last_post_id,
    SUBSTRING_INDEX(GROUP_CONCAT(`p`.`date` ORDER BY `p`.`id` DESC SEPARATOR "| " ), "| ", 1) as last_post_date,
    IFNULL(MAX(p.date), t.date) AS pts
FROM
    `topics` t
LEFT JOIN
    `posts` p ON `p`.`topics_id` = `t`.`id`
LEFT JOIN
    `users` u ON `u`.`id` = `t`.`user_id`
GROUP BY
    `t`.`id`
ORDER BY
    `pts` DESC
LIMIT 10

我在这里有10个最新的主题标题,他们的作者用户名和ID,每个主题中的消息数,每个主题的最后ID和发布日期,以及按活动排序的所有内容......基本上所有内容。我需要的只是作者最后帖子的用户名。我想我必须使用子查询进行一次左连接,但我有点卡住了。 有人能帮助我吗?

1 个答案:

答案 0 :(得分:1)

而不是形成包含整个帖子的帖子的串联的字符串,然后从中获取第一个子字符串(由id排序),这不仅是性能拖累(因为它不可思议并且需要昂贵的字符串操作)但也受到错误的影响(如果分隔符恰好出现在连接的字符串中,或​​者连接的结果超出MySQL的限制)...

您真正想做的是获取groupwise maximum,这可以通过将posts表与子查询加在一起来获得。然后,您只需要第二次加入users表(这次是针对上一篇文章)以获取所需的用户名:

SELECT   topic.id
 ,       topic.title
 ,       topic.date
 ,       topic.user_id
 ,       topic_user.username
 ,       t.count_posts
 ,       lastpost.id
 ,       lastpost.date
 ,       lastpost_user.username
 ,       IFNULL(lastpost.date, topic.date) AS pts

FROM     topics topic
         LEFT JOIN users topic_user ON topic_user.id = topic.user_id
         LEFT JOIN (
           (
             SELECT   topics_id
               ,      COUNT(*)  AS count_posts
               ,      MAX(date) AS date
             FROM     posts
             GROUP BY topics_id
           ) t  JOIN posts lastpost USING (topics_id, date)
           LEFT JOIN users lastpost_user ON lastpost_user.id = lastpost.user_id
         ) ON lastpost.topics_id = topic.id

ORDER BY pts DESC

LIMIT    10

请注意,我还要lastpost而不是date来识别id,因为合成键不应该用于确定自然属性;但是,这假设date实际上是一个时间戳。