【问题标题】:Get newest result with GROUP BY in SQL based on JOIN基于 JOIN 在 SQL 中使用 GROUP BY 获取最新结果
【发布时间】:2014-11-07 01:10:03
【问题描述】:

我有两个 SQL 表 usersmessages,如下所示:

user_id | username
--------|---------
      1 | alice
      2 | bob
      3 | carol

message_id | sending_user_id | message | created_utc
-----------|-----------------|---------|-------------
          1|               1 | a       | 67
          2|               1 | b       | 68
          3|               3 | c       | 69
          4|               2 | d       | 70
          5|               3 | e       | 71
          6|               1 | f       | 72

我正在尝试编写一个 SQL 查询,该查询将为每个 user 生成最新的 message,由 created_utcmessage 降序排列。所以结果应该是这样的:

message_id | sending_user_id | message | created_utc | sending_username
-----------|-----------------|---------|-------------|----------------------
          6|               1 | f       | 72          | alice
          5|               3 | e       | 71          | carol
          4|               2 | d       | 70          | bob

我不知道如何使用以下查询保证消息始终是最新的:

SELECT messages.message_id, messages.sending_user_id, messages.message, messages.created_utc, users.username AS sending_username
FROM messages 
LEFT JOIN ON users 
WHERE messages.sending_user_id=users.user_id 
GROUP BY messages.sending_user_id
ORDER BY messages.created_utc DESC

编辑:我使用的是 PostgreSQL 9.3.5

【问题讨论】:

标签: sql postgresql greatest-n-per-group


【解决方案1】:

对于 Postgres,我会推荐 distinct on:

SELECT DISTINCT ON (m.sending_user_id) m.message_id, m.sending_user_id, m.message, m.created_utc,
       u.username AS sending_username
FROM messages m LEFT JOIN
     users u
     on m.sending_user_id = u.user_id 
ORDER BY m.sending_user_id, m.created_utc DESC;

如果您想要最终的order by,请使用子查询:

SELECT um.*
FROM (SELECT DISTINCT ON (m.sending_user_id) m.message_id, m.sending_user_id, m.message, m.created_utc,
              u.username AS sending_username
      FROM messages m LEFT JOIN
           users u
           on m.sending_user_id = u.user_id 
      ORDER BY m.sending_user_id, m.created_utc DESC
     ) um
ORDER BY created_utc;

【讨论】:

  • 这保证了最新消息,但不按照created_utc列排序。
【解决方案2】:

我认为最好的(也是最灵活的)ANSI SQL 解决方案是NOT EXISTS

SELECT    m1.message_id, m1.sending_user_id, m1.message, m1.created_utc, users.username AS sending_username
FROM      messages m1 
LEFT JOIN users ON (m1.sending_user_id=users.user_id)
WHERE     NOT EXISTS (
            SELECT *
            FROM   messages m2
            WHERE  m2.sending_user_id = m1.sending_user_id
            AND    m2.created_utc < m1.created_utc
          )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-07
    • 2013-03-12
    • 1970-01-01
    • 2017-09-03
    • 2016-05-15
    相关资源
    最近更新 更多