ROW_NUMBER() assigns 1, 2, 3 always (ties broken by an ORDER BY). RANK() assigns 1, 2, 2, 4 (gaps). DENSE_RANK() assigns 1, 2, 2, 3 (no gaps). For “give me the latest record per user” use ROW_NUMBER() with a partitioned ORDER BY. For “give me ties the same rank” use DENSE_RANK().
Latest message per user: select user_id, body from (select *, row_number() over (partition by user_id order by ts desc) rn from messages) where rn = 1;
Top-K within group: same pattern with rn <= K.
Tied ranking: dense_rank() over (partition by … order by score desc).
partition by user_id -> rank rows
ORDER BY ts desc (or score desc)
ROW_NUMBER RANK DENSE_RANK
1,2,3 1,2,2,4 1,2,2,3
ROW_NUMBER for “the one”. DENSE_RANK for “the same tier”. RANK when you keep the gap.