Как мне присоединиться к последней записи в таблице? - PullRequest
4 голосов
/ 19 мая 2009

То, что мне нужно сделать, просто ... но сейчас 3 часа ночи, и я, наверное, упускаю из виду очевидное.

Я пишу простой форум. В одной таблице хранятся названия форумов, описания и т. Д., А в другой - сообщения. В списке форумов, который показывает список всех форумов, я хочу получить последнее сообщение на каждом форуме и отобразить тему сообщения, постера и идентификатор сообщения, а также дату. Простой.

Единственная проблема заключается в том, что когда я присоединяюсь к таблице сообщений, она присоединяется к первой записи в таблице, а не к последней, что будет означать последнее сообщение в этом форуме.

Вот упрощенный запрос, который получает список форумов + данные для «последнего» поста (который теперь функционирует как «первый пост»).

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

Как я могу это исправить?

1 Ответ

5 голосов
/ 19 мая 2009

Проблема, с которой вы столкнулись, - это классическая Неоднозначная проблема GROUP BY . Это относится к MySQL, потому что другие RDBMS (и стандартный 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 - автоинкремент).


Комментарий:

Небольшая проблема с этим. 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))
...