detailCode :
Using the table (Messages) data structure:
+------+--------+--------+----------+------+--------+
| id | FromId | ToId | sentdate | text | index |
+------+--------+--------+----------+------+--------+
| guid | 200 | 100 | 3/9/20 | 2c | 6 |
| guid | 400 | 100 | 3/8/20 | 4a | 5 |
| guid | 100 | 200 | 3/8/20 | 2b | 4 |
| guid | 300 | 100 | 3/7/20 | 3a | 3 |
| guid | 200 | 100 | 3/6/20 | 2a | 2 |
| guid | 300 | 200 | 3/5/20 | 1a | 1 |
+------+--------+--------+----------+------+--------+
SELECT *
FROM `Messages`
WHERE FromId IN (
SELECT DISTINCT FromId
FROM `Messages`
WHERE ToId = '100')
GROUP BY FromId ORDER BY index DESC
The expected results should be (newest record from each sender):
+------+--------+--------+----------+------+--------+
| id | fromid | toid | sentdate | text | index |
+------+--------+--------+----------+------+--------+
| guid | 200 | 100 | 3/9/20 | 2c | 6 |
| guid | 400 | 100 | 3/8/20 | 4a | 5 |
| guid | 300 | 100 | 3/7/20 | 3a | 3 |
+------+--------+--------+----------+------+--------+
However, after doing GROUP BY, the following results occur (incorrect sorting):
+------+--------+--------+----------+------+--------+
| id | fromid | toid | sentdate | text | index |
+------+--------+--------+----------+------+--------+
| guid | 400 | 100 | 3/8/20 | 4a | 5 |
| guid | 300 | 100 | 3/7/20 | 3a | 3 |
| guid | 200 | 100 | 3/6/20 | 2a | 2 |
+------+--------+--------+----------+------+--------+
How do you get the latest records distinctively from each sender optimized without returning all records? I've tried JOINs and ORDER BY in the subquery, with the same results.
GMB :
If you want entire records, you need filtering, not aggregation.
If you are running MySQL 8.0, you can use row_number()
:
select *
from (
select m.*, row_number() over(partition by fromid order by sentdate desc) rn
from messages m
) t
where rn = 1
You can also filter with a correlated subquery (this will work on older versions of MySQL):
select m.*
from messages m
where m.sentdate = (
select max(m1.sentdate) from messages m1 where m1.fromid = m.fromid
)
With an index on (fromid, sentdate)
, the correlated subquery might be an efficient solution.