从联盟获取具有最大值的行

时间:2011-11-06 18:50:59

标签: sql postgresql aggregate-functions

论坛

  • forum_id
  • 名称

线程

  • 的thread_id
  • forum_id
  • USER_ID
  • added_ts

thread_replies

  • thread_reply_id
  • 的thread_id
  • USER_ID
  • added_ts

用户

  • USER_ID
  • 用户名

问题

我想返回一个论坛列表,其中包含最新帖子。有效率的。部分问题是帖子在线程和thread_replies之间分开。

我的第一直觉是获得一个UNION of threads和thread_replies以及我需要的数据:

SELECT * FROM ((SELECT forum_id, thread_id, user_id, added_ts FROM threads t)
UNION (SELECT t1.forum_id, r.thread_id, r.user_id, r.added_ts FROM thread_replies r 
      INNER JOIN threads t1 ON t1.thread_id = r.thread_id)) messages;

现在我有一个包含forum_id,thread_id,user_id和added_ts的所有帖子的列表。我的下一个本能是在论坛表上加入这个表,但是我没有看到一个明确的方法,只将每个论坛的added_ts的最新值减去,同时仍然返回剩余的所需数据。

SELECT * FROM forums f 
INNER JOIN 
  (SELECT messages.*, users.username FROM
     ((SELECT forum_id, thread_id, user_id, added_ts FROM threads t) 
       UNION 
      (SELECT t1.forum_id, r.thread_id, r.user_id, r.added_ts 
       FROM thread_replies r 
       INNER JOIN threads t1 ON t1.thread_id = r.thread_id)) messages 
       INNER JOIN users ON messages.user_id = users.user_id 
       ORDER BY messages.added_ts) last_replies ON last_replies.forum_id = f.forum_id;

我尝试了GROUP BY forum_id,加上MAX(last_replies.added_ts),但这些是我可以使用group by和聚合函数选择的结果集中的唯一两个字段,我可以告诉你。

SELECT f.forum_id, MAX(last_replies.added_ts)
FROM forums f
INNER JOIN (
   SELECT messages.*, users.username
   FROM (
      (SELECT forum_id, thread_id, user_id, added_ts
       FROM threads t)
      UNION
      (SELECT t1.forum_id, r.thread_id, r.user_id, r.added_ts
       FROM thread_replies r
       INNER JOIN threads t1 ON t1.thread_id = r.thread_id)) messages
       INNER JOIN users ON messages.user_id = users.user_id
      ORDER BY messages.added_ts
        ) last_replies ON last_replies.forum_id = f.forum_id GROUP BY f.forum_id;

我认为可能有一种方法可以使用ORDER BY added_ts DESC和LIMIT 1来做到这一点,但我似乎无法看到如何使这项工作。我希望在这里得到一些好的想法,可以引导我朝着正确的方向前进。

解决方案

根据下面选择的解决方案,我提出了这个问题:

SELECT f.*, last_replies.*, u.username 
FROM forums f 
INNER JOIN (
    SELECT DISTINCT ON (messages.forum_id) messages.*
    FROM (
        (SELECT forum_id, thread_id, user_id, added_ts FROM threads t)
    UNION
        (SELECT t1.forum_id, r.thread_id, r.user_id, r.added_ts FROM thread_replies r INNER JOIN threads t1 ON t1.thread_id = r.thread_id)
    ) messages
   ORDER BY messages.forum_id, messages.added_ts DESC
) last_replies ON last_replies.forum_id = f.forum_id
INNER JOIN users u ON last_replies.user_id = u.user_id;

1 个答案:

答案 0 :(得分:2)