I have a messaging app where I need to return all of the conversations that a user is part of and the messages associated with each one. I'd like to limit the number of messages per conversation.
Table structure is as follows:
Users
| id | name | email | created_at |
|------|------|----------|------------|
| 1 | Bob | a@b.com | timestamp |
| 2 | Tom | b@b.com | timestamp |
| 3 | Mary | c@b.com | timestamp |
Messages
| id | sender_id | conversation_id | message | created_at |
|------|-----------|------------------|---------|------------|
| 1 | 1 | 1 | text | timestamp |
| 2 | 2 | 2 | text | timestamp |
| 3 | 2 | 1 | text | timestamp |
| 4 | 3 | 3 | text | timestamp |
Conversations
| id | created_at |
|----|------------|
| 1 | timestamp |
| 2 | timestamp |
| 3 | timestamp |
Conversations_Users
| id | user_id | conversation_id |
|----|---------|-----------------|
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 2 | 2 |
| 3 | 3 | 2 |
| 4 | 3 | 3 |
| 5 | 1 | 3 |
I want to load up all the conversations that user (id 1) is in (In the case of the example - conversation 1 and 3). For each conversation I need the messages associated with it, grouped by conversation_id
, ordered by created_at ASC
. My current query handles this:
SELECT
*
FROM
messages
WHERE
conversation_id IN (
SELECT
conversation_id
FROM
conversations_users
WHERE
user_id = 1
)
ORDER BY
conversation_id, created_at ASC;
However, that would stick a lot of data into memory. Therefore, I'd like to limit the number of messages per conversation.
I've looked at rank()
and ROW_NUMBER()
but am unsure how to implement them/if they are what's needed.