【问题标题】:postgres group by aggregate functionpostgres 按聚合函数分组
【发布时间】:2011-04-11 09:43:12
【问题描述】:

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

+------------+-------------+----------+
| 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 对应的消息。

有什么方法可以解决这个问题还是我用错了方法?

【问题讨论】:

  • 你是什么版本的?

标签: sql postgresql group-by


【解决方案1】:

这个:

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) 上创建一个索引以使其快速工作。

您可能会觉得这篇文章很有趣:

【讨论】:

  • 这一个给出了不同的结果,排序顺序不同。
  • @Frank:您可以将其用作子查询并使用上级查询重新排序结果。
  • @Frank:原问题没有提到sender_id上的顺序,但这里是更正顺序的查询。
  • 关于这篇文章,我不能使用任何 8.4 的方法,比如我在 8.3 上的 windows 功能。您在那里给出的第二个查询给出了一个错误(“mi”处或附近的语法错误)。我需要按日期订购,所以也不能在那里使用 DISTINCT ON 的想法。
  • @johnnymire:查看帖子更新。至于第二个查询,它在哪一行给出错误?
【解决方案2】:

使用相关子查询:

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

子查询为上层查询处理的每一行重新计算。

【讨论】:

    【解决方案3】:

    在不同的地方使用:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-11
      • 2017-07-08
      • 1970-01-01
      相关资源
      最近更新 更多