postgres group by aggregate function

时间:2010-09-12 19:19:00

标签: sql postgresql group-by

我有一个消息表,如下所示:

+------------+-------------+----------+
| sender_id  |  created_at | message  |
+------------+-------------+----------+
|      1     | 2010-06-14  | the msg  |
|      1     | 2010-06-15  | the msg  |
|      2     | 2010-06-16  | the msg  |
|      3     | 2010-06-14  | the msg  |
+------------+-------------+----------|

我想为每个发件人选择最近的单个邮件。

这看起来像是GROUP BY sender_id和ORDER BY created_at,但是我无法选择最新的消息。

我正在使用postgres,因此如果我想按该字段排序,则需要在SELECT语句中的created_at字段上使用聚合函数,因此我正在考虑做这样的事情作为初始测试

SELECT messages.sender_id, MAX(messages.created_at) as the_date 
FROM messages 
GROUP BY sender_id 
ORDER BY the_date DESC 
LIMIT 10;

这似乎有效,但当我想选择“消息”时,我也不知道要使用哪种聚合函数。我基本上只想要与MAX created_at对应的消息。

有没有办法解决这个问题,或者我是以错误的方式接近它?

3 个答案:

答案 0 :(得分:7)

此:

SELECT  *
FROM    (
        SELECT  DISTINCT ON (sender_id) *
        FROM    messages 
        ORDER BY
                sender_id, created_at DESC 
        ) q
ORDER BY
        created_at DESC
LIMIT 5

或者这个:

SELECT  (mi).*
FROM    (
        SELECT  (
                SELECT  mi
                FROM    messages mi
                WHERE   mi.sender_id = m.sender_id
                ORDER BY
                        created_at DESC
                LIMIT 1
                ) AS mi
        FROM    messages m
        GROUP BY
                sender_id
        ) q
ORDER BY
        (mi).created_at  DESC
LIMIT 5

(sender_id, created_at)上创建一个索引,以便快速工作。

您可能会发现这篇文章很有趣:

答案 1 :(得分:1)

使用相关的子查询:

select * from messages m1 
where m1.created_at = (
    select max(m2.create_at) 
    from messages m2 
    where m1.sender_id = m2.sender_id
);

对上层查询处理的每一行重新评估子查询。

答案 2 :(得分:0)

使用distinct on:

    SELECT DISTINCT ON (sender_id) 
           sender_id,created_at,message
      FROM messages
  ORDER BY sender_id,created_at DESC