Я создаю частную систему обмена сообщениями для сайта знакомств. У меня проблемы с группой по запросу. Вот структура таблицы:
`id` bigint (20) NOT NULL AUTO_INCREMENT ,
`fromme` integer (11) NOT NULL,
`tome` integer (11) NOT NULL,
`subject` varchar (255) NOT NULL,
`message` longtext NOT NULL,
`mydate` datetime NOT NULL,
`thread` varchar (255) NOT NULL,
`receipt` varchar (50) NOT NULL,
`INDELETE` varchar (5),
`SENTDELETE` varchar (5),
PRIMARY KEY (`id`)
Когда пользователь отправляет новое сообщение другому пользователю, он генерирует случайную строку для отслеживания потока. Как они отвечают, он несет строку нити (похожую на facebook). Когда пользователь входит в систему, они могут видеть все сообщения в своем почтовом ящике и в зависимости от того, является ли это новым сообщением, он изменяет цвет bg строки. Все это работает нормально, за исключением статуса получения сообщения, которое было вложено туда и обратно. Это запрос:
select messages.id, messages.fromme, messages.subject, messages.message, messages.receipt, messages.mydate, messages.thread, users.firstname, users.lastname, users.image1
from messages, users
where messages.tome = '40' and messages.INDELETE !='y' and messages.fromme = users.id
GROUP BY messages.thread
ORDER BY messages.mydate desc
Он возвращает его правильно, но группа по функции возвращает сообщение FIRST потока. Мне нужен ПОСЛЕДНИЙ, чтобы он работал правильно. Кто-нибудь знает, как это сделать?
Чтобы получить преимущество предложения GROUP BY, вам нужна сводная функция (MAX, SUM, COUNT и т.д.). Вероятно, вы захотите использовать этот подзапрос, чтобы выработать последнее сообщение (самый высокий ID) в каждом потоке:
select MAX(messages.id) id, messages.thread
FROM messages
GROUP BY messages.thread
Объединяя все это, вы можете использовать
SELECT messages.id,
messages.fromme,
messages.subject,
messages.message,
messages.receipt,
messages.mydate,
messages.thread,
users.firstname, users.lastname, users.image1
FROM messages,
users,
(SELECT MAX(messages.id) id, messages.thread thread
FROM messages
GROUP BY messages.thread) latest,
WHERE messages.tome = '40'
AND messages.INDELETE !='y'
AND messages.fromme = users.id
AND messages.id=latest.id
ORDER BY messages.mydate desc
Ответ @Ollie Jones в порядке (за исключением устаревшего синтаксиса соединения в стиле запятой SQL-89), но для чего он стоит здесь:
SELECT m1.*, u.*
FROM messages m1
LEFT OUTER JOIN messages m2
ON (m1.thread=m2.thread AND m1.mydate < m2.mydate)
JOIN users u ON (m1.fromme = u.id)
WHERE m2.thread IS NULL;
Нет GROUP BY
. Это соответствует каждой строке m1
гипотетической строке m2
, которая имеет тот же поток и более позднюю дату. Если нет строки m2
, которая соответствует, то m1
должно быть последним сообщением в потоке.
Это решение подходит для MySQL, потому что MySQL обычно создает временную таблицу, сортируя запросы GROUP BY
. Решение соединения часто выполняется быстрее. Убедитесь, что у вас есть индекс (thread, mydate).