Насчет "многократно", наверное, я погорячился немного.
Сорри :) Но всё равно сначала будут выбраны все без исключения данные (в подзапросе - а если их там миллион?), а потом только они будут группироваться. Нарушение здравого смысла (сути использования БД) происходит по-любому. Да, согласен, что для небольшого количества данных так можно сделать. Когда заранее известно, что данных немного будет.
Медведь, мой запрос с учетом "утренней поправки" получается такой:
select
id_user,
username,
(select message from messages m2 where m2.id_user=m1.id_user order by msg_date desc limit 1) as msg,
msg_date
from messages m1
group by id_user
Тут происходит следующее.
1. Делается выборка уникальных юзеров (группировка по id_user).
2. В каждой строке делается подзапрос: выбираем единственное значение из поля "сообщение", при этом из внешнего запроса передаем m1.id_user во внутренний запрос, где используем его для фильтрации m2.id_user=m1.id_user. Это позволяет выбрать все сообщения именно того юзера, чьи данные у нас имеются в строке внешнего запросе. Также во внутреннем запросе за счет сортировки будет поднята наверх запись с самой последней датой. И за счет ЛИМИТа бы возьмем только одну запись. Из которой выделим поле message и вернем его во внешний запрос. Где ему присвоим алиас msg. Всё, готово :) На самом деле, это всё весьма просто.
Что касается запроса с JOIN, то он мне не нравится :) В немалой степени потому, что там заложено, что возрастание даты на 100% соответствует возрастанию id. А это может быть не совсем так. И тогда запрос получается не верный. И самое главное, что он изначально СЕМАНТИЧЕСКИ не верный, т.к. если речь идет о "последней дате", то и надо дату использовать.
Хотя, конечно, по сути этот запрос близок к тому, что у меня написано. Но он менее гибкий, на мой взгляд.
_____________
*
Хэлп по PHP*
Описалово по JavaScript *
Хэлп и СУБД для PostgreSQL*
Обучаю PHP, JS, вёрстке. Интерактивно и качественно. За разумные деньги. *
"накапливаю умение телепатии" (С) и "гуглю за ваш счет" (С)