SELECT user_id, MAX(post_id)
FROM posts
WHERE user_id
IN (SELECT friend_id
FROM friends
WHERE user_id = UserId)
GROUP BY user_id;
Однако, поскольку MySQL всех версий не умеет адекватно оптимизировать внешний запрос вне зависимости от созданных индексов и их явного указния через FORCE(key list), разбиваем сложный запрос на два простых: в первом запросе получаем список пользователей, а во втором – выбираем посты.
--------------
а бы сказал автор не умеет sql :)
select p.user_id, max(p.post_id) from posts p, friends f where p.user_id=f.friend_id and f.user_id=UserID group by user_id;
По ходу-дела автор PG знает хуже чем MySQL. В самих запросах исходя из его структуры допущены ошибки. И в структуре. Уже лень искать и цитировать, но если не ошибаюсь, где то там была строка где выбираем пользователя и количество его сообщений MAX - записей. При этом MySQL придется просматривать всю таблицу подсчитывая количество записей принадлежащих пользователю. Лучше было бы завести счетчик сообщений, содержащий в себе количество записей оставленных пользователем. Причем по-скольку количество оставленных мной записей не самый важный параметр, его обновление может идти с задеркой. Точно не скажу, потому что почитал и закрыл.
Еще проблема - у нас есть таблица friendId, userId - в этой таблице 2 поля типа интегер. Ставить индекс на два таких поля безсмысленно - ведь выборка будет идти только по UserID - типа найти друга этого юзера. ПОэтому обращение к индексу составленному по двум единственным полям постоянной длины - лишь лишние операции - придется сначала читать индекс, потом находить. В зависимости от частоты запросов надо было бы составить индекс по полю userId отдельно, а еще завести дополнительное поле со счетчиком. А можно индекс и не составлять а потом по мере анализа частоты тех или иных запросов делать вывод.
Я так, по памяти пишу, может где-то и ошибся, но точно ошибки были в проектировании.