我正在使用非常标准的消息模型构建Rails 3应用程序。我想为每个唯一的conversation_id返回最近创建的消息记录。这似乎是一项相当简单的任务,但我无法编写或找到有效的解决方案 不可否认,我也不是超级SQL精明(因为我到目前为止主要使用Active Record查询)。这就是我想要完成的事情。
示例消息表:
| id | sender_id | receiver_id | conversation_id | subject | body | created_at |
| 1 | * | * | 1 | * | * | 16:01 |
| 2 | * | * | 2 | * | * | 17:03 |
| 3 | * | * | 1 | * | * | 18:04 |
| 4 | * | * | 3 | * | * | 19:06 |
| 5 | * | * | 2 | * | * | 20:07 |
| 6 | * | * | 1 | * | * | 21:08 |
| 7 | * | * | 4 | * | * | 22:09 |
我希望得到的回报最多"最近"每个conversation_id
的消息记录,并按created_at DESC
排序:
| id | sender_id | receiver_id | conversation_id | subject | body | created_at |
| 7 | * | * | 4 | * | * | 22:09 |
| 6 | * | * | 1 | * | * | 21:08 |
| 5 | * | * | 2 | * | * | 20:07 |
| 4 | * | * | 3 | * | * | 19:06 |
我在SQLite中的原始解决方案工作正常:GROUP BY (conversation_id)
。但是,显然该解决方案是SQLite独有的,不适用于Postgres。
接下来,我尝试了:SELECT DISTINCT ON (conversation_id) *
。但是,这也需要我不想要的ORDER BY (conversation_id)
。我想按created_at
订购。
答案 0 :(得分:2)
DISTINCT ON
如果您使用DISTINCT ON
,则需要一个子查询:
SELECT *
FROM (
SELECT DISTINCT ON (conversation_id) *
FROM message t
ORDER BY conversation_id, created_at DESC
) sub
ORDER BY created_at DESC;
子查询中的顺序必须与DISTINCT ON
子句中的列一致,因此必须将其包装在外部查询中以达到所需的排序顺序。
row_number()
类似的故事,你也需要一个子查询:
SELECT id, sender_id, receiver_id, conversation_id, subject, body, created_at
FROM (
SELECT *, row_number() OVER (PARTITION BY conversation_id
ORDER BY created_at DESC) AS rn
FROM message t
) sub
WHERE rn = 1
ORDER BY created_at DESC;
也可能更慢。