То, что мне нужно сделать, просто … но его 3am и Im, вероятно, игнорируют очевидное.
Im кодирует простой форум. В одной таблице хранятся названия, описания и т. Д., А в других – записи. В списке форумов, в котором показан список всех форумов, я хочу получить последнюю запись на каждом форуме и отобразить тему сообщения, постер и почтовый идентификатор и дату. Просто.
Единственная проблема заключается в том, что когда я присоединяюсь к таблице posts, она присоединяется к первой записи в таблице, а не к последней, которая будет обозначать последнее сообщение на этом форуме.
Вот упрощенный запрос, который получает список форумов + данных для «последнего» сообщения (которое теперь функционирует как «первый пост»).
SELECT forum_title, forum_id, post_subject, post_user, post_id, post_date FROM board_forums LEFT JOIN board_posts ON (forum_id = post_parentforum AND post_parentpost = 0) WHERE forum_status = 1 GROUP BY forum_id ORDER BY forum_position
Как я могу это исправить?
Проблема, с которой вы сталкиваетесь, – это классическая проблема неоднозначной GROUP BY . Это особенно важно для MySQL, поскольку другие СУБД (и стандартный SQL) не позволят ваш запрос вообще. В вашем запросе не выполняется правило с одним значением, потому что вы не указали все неагрегированные столбцы в GROUP BY
.
Вот решение, демонстрирующее мой любимый способ получить наибольшую строку для каждой группы:
SELECT f.forum_title, f.forum_id, p1.post_subject, p1.post_user, p1.post_id, p1.post_date FROM board_forums f LEFT JOIN board_posts p1 ON (f.forum_id = p1.post_parentforum AND p1.post_parentpost = 0) LEFT JOIN board_posts p2 ON (f.forum_id = p2.post_parentforum AND p2.post_parentpost = 0 AND p1.post_id < p2.post_id) WHERE p2.post_id IS NULL AND f.forum_status = 1 ORDER BY f.forum_position;
Если p2.post_id IS NULL
, это означает, что никакая запись не найдена в p2
которая больше, чем сообщение, найденное в p1
.
Ergo, p1
– последнее сообщение (при условии, что post_id
автоматически увеличивается).
Re:
Небольшая проблема с этим. post_id с самым высоким ID не обязательно является последним сообщением.
Нет проблем. Просто используйте столбец, который, как гарантируется, отличает предыдущую запись от более поздней публикации. Вы post_date
. В случае связей вам придется разорвать связи с другим столбцом (или столбцами), который обязательно будет в хронологическом порядке.
LEFT JOIN board_posts p2 ON (f.forum_id = p2.post_parentforum AND p2.post_parentpost = 0 AND (p1.post_date < p2.post_date OR p1.post_date = p2.post_date AND p1.post_millisecond < p2.post_millisecond))