2014-11-07 56 views
1

我有两个SQL表usersmessages它看起来像这样:获取最新的结果与GROUP BY基于JOIN

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查询,将导致最新messageusercreated_utc排列的message取消。所以结果应该是这样的:

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

+0

请标记与你的问题你正在使用的数据库。 – 2014-11-07 01:11:47

+0

@GordonLinoff done – 2014-11-07 01:14:54

+1

许多相同的问题。 http://stackoverflow.com/questions/3800551/select-first-row-in-each-group-by-group/7630564 – 2014-11-07 02:55:27

回答

3

随着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; 
+0

这保证了最新的消息,但不按照'created_utc'列排序表。编辑完成后 – 2014-11-07 01:33:14

+0

完美! – 2014-11-07 01:39:32

0

我认为最好的(也是最灵活)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 
     )