Reputation: 87
For example, I have such sql table of messages:
Id from_user_id to_user_id message 1 1 2 Hello 2 1 2 How are you? 3 1 3 Where are you?
And query SELECT DISTINCT to_user_id FROM messages; it returns
to_user_id 2 3
But, that is not enough. I need to show all last messages of from_user_id(id=1) to others users, and avoid N+1 queries problem. The result must be like this
Id from_user_id to_user_id message 2 1 2 How are you? 3 1 3 Where are you?
Upvotes: 1
Views: 161
Reputation: 1269753
Postgres offers distinct on
, which is generally the best way to approach this type of problem:
select distinct on (to_user_id) m.*
from messages m
where m.from_user_id = 1
order by to_user_id, id desc;
Upvotes: 1
Reputation: 18808
You could use the analytic function rank, and order it within a group...
select * from (
select id,
from_user_id,
to_user_id,
message,
rank () over (partition by from_user_id, to_user_id order by id desc) rnk
from table_name
) t1 where rnk = 1
This is assuming that the id column is sequentially generated number, so message with id 3 was created after message with id 2. Usually, if you have a timestamp column, it would be more logical. In that case, you could use order by timestamp desc
Upvotes: 1
Reputation: 11478
You're going to want to do a self join:
SELECT m.*
FROM messages m
LEFT JOIN messages _m ON m.to_user_id = _m.to_user_id
AND _m.id > m.id
WHERE _m.id IS NULL
Upvotes: 1