Не думаю, что в вашем запросе слишком много подзапросов, но его можно написать более оптимально. Я думаю, что следующий запрос должен работать одинаково хорошо:
SELECT `PM`.`message_id`, `PM`.`thread_id`, `PM`.`body`, `U`.`username`
FROM `users` `U`
INNER JOIN `personal_messages` `PM` ON `PM`.`from_id` = `U`.`user_id`
ORDER BY `PM`.`message_date` DESC;
Проблемы, которые я обнаружил по вашему запросу:
- Первый подзапрос -
SELECT MAX(message_id) from personal_messages GROUP BY thread_id
- всегда будет возвращать один набор результатов, поэтому использование IN не имеет смысла
- Для второго подзапроса -
SELECT users.id FROM users WHERE users.id = personal_messages.from_id
- вместо этого вы можете использовать INNER JOIN, как в моем примере
Надеюсь, что вышеупомянутое помогает.
Кроме того, я не уверен, какую информацию вы на самом деле пытаетесь получить. Но приведенный выше запрос должен предоставить вам детали самого последнего сообщения, а также его идентификатор потока и имя пользователя.
РЕДАКТИРОВАНИЕ запрос, чтобы выбрать одно последнее сообщение в теме:
SELECT *
FROM (
SELECT `PM`.`message_id`, `PM`.`thread_id`, `PM`.`body`, `U`.`username`
FROM `users` `U`
INNER JOIN `personal_messages` `PM` ON `PM`.`from_id` = `U`.`user_id`
ORDER BY `PM`.`message_date` DESC;
) `TT`
GROUP BY `TT`.`thread_id`;