Подскажите как правильно сделать запрос к базе MySQL

filipchuk

Новичок
у меня похожая задача - получить последних 5 сообщений форума, темы этих сообщений должны быть разные (тоесть не должны выбираться сообщения одной темы)

но не могу понять как запрос построить.
вот это не работает правильно
SELECT (m.ID_TOPIC), m.ID_MSG
FROM (smf_messages AS m)
GROUP BY m.ID_TOPIC
ORDER BY m.ID_TOPIC DESC
LIMIT 0, 5

Возможно, задачу надо решать через Join, кто знает?
 

Фанат

oncle terrible
Команда форума
nimistar
если ты не можешь представить себе структуру базы в такой стандартной задаче, то, может, не стоит торопиться отвечать?

-~{}~ 25.05.07 14:09:

filipchuk
проще всего будет сделать 5 запросов.
 

filipchuk

Новичок
2 Фанат

Это вариант, просто думал это можна 1 запросом сделать, но наверно попробую как ты посоветовал, а там видно будет :)
 

amadeus

Новичок
SELECT `id_topic`, max( `id_msg` ) AS `max_in_topic`
FROM `smf_messages`
GROUP BY `id_topic`
ORDER BY `max_in_topic` DESC
LIMIT 0 , 5
Это само-собой если максимальное id_msg является самым свежим, но это скорее всего так и есть.

-~{}~ 25.05.07 15:15:

Можно ещё выбрать то же самое отталкиваясь от таблицы топиков, если такая есть. То есть выбирать записи из таблицы топиков и в связи с ними максимальный id сообщения в этом топике и сортировать по id-сообщения. Вариантов текста самого запроса может быть даже несколько.
 

amadeus

Новичок
Отталкивался от того, что было в вопросе. Там выбираются только id.
Над идеальным запросом нужно подумать. А если сходу, то такой вот большой и страшный выберет всё:
SELECT *
FROM `smf_messages` , (
SELECT `id_topic`, max( `id_msg` ) AS `max_in_topic`
FROM `smf_messages`
GROUP BY `id_topic`
ORDER BY `max_in_topic` DESC
LIMIT 0 , 5
) AS `query`
WHERE `messages`.`id_msg` = `query`.`max_in_topic`
 

Фанат

oncle terrible
Команда форума
кстати, да. че-то я не подумал.
если выбирать по дате, то не получилось бы. а по id должно получиться джойном.
и БЕЗ вложенных запросов, которые есть зло.

выбираем макс айди группируя по топик_айди и джойним на саму себя, выбирая по id_msg = id_msg
а?
 

filipchuk

Новичок
Сделал как посоветовал вначале Фанат, все работало, потом переделал как написал amadeus, все отлично :)

спасибо, именно то что надо
 

Bitterman

Новичок
Фанат
выбираем макс айди группируя по топик_айди и джойним на саму себя, выбирая по id_msg = id_msg
Может я, конечно, чего-то и недопонял, но что-то не получается. Нам в условии JOIN надо выбрать строку с id равным максимальному. Как? Ежели просто t1.id=t2.id, то выбирается первая попавшаяся строка.
 

Фанат

oncle terrible
Команда форума
почему первая попавшаяся? все t1.id будут максимальными для каждого топика, вроде бы

-~{}~ 25.05.07 17:31:

спасибо, именно то что надо
я бы, все-таки, за написание на форуме вложенных селектов расстреливал
 

amadeus

Новичок
Фанат,
пожалуйста, напиши текст запроса, в котором таблица будет объединяться сам с собой, а не с запросом. Могу представить несколько вариантов решения вопроса. Можно предыдущий запрос переделать к синтаксису с join. Можно вот так ещё:
SELECT *
FROM `smf_messages`
WHERE `id_msg`
IN (

SELECT max( `id_msg` ) AS `max_in_topic`
FROM `smf_messages`
GROUP BY `id_topic`
)
ORDER BY `id_msg` DESC
LIMIT 0 , 5
но уже полчаса думаю и не могу обойтись без ЗЛА. Опыта и знаний не хватает, а интересно.
 

Фанат

oncle terrible
Команда форума
Могу представить несколько вариантов решения вопроса. Можно предыдущий запрос переделать к синтаксису с join.
ну, вот об этом я и говорю. "переделать" к синтаксису с join
 

amadeus

Новичок
с join то c join, но объединяться через join таблица всё равно у меня будет с запросом, ты так имел ввиду?
 

Bitterman

Новичок
Фанат
почему первая попавшаяся? все t1.id будут максимальными для каждого топика, вроде бы
[sql]
SELECT MAX(dp.ID), dp.DiscussionID, dp1.ID
FROM DiscussionPost as dp
LEFT JOIN DiscussionPost as dp1 ON dp1.ID=dp.ID
GROUP BY dp.DiscussionID
[/sql]
Вот в таком запросе dp1.ID выбирается первая попавшаяся, а нужна максимальная.
 

Фанат

oncle terrible
Команда форума
ты попробовал или так думаешь?

просто "первый попавшийся" действительно выбирается, но это если без джойна делать, а выбирать остальные поля вместе с максом.
а в таком джойне я просто не понимаю, откуда взьмется первый попавшийся.

Ну, возможно, я и ошибаюсь
приеду из лесу - попробую.
 

Bitterman

Новичок
Фанат
ты попробовал или так думаешь?
Пробовал
а в таком джойне я просто не понимаю, откуда взьмется первый попавшийся.
Насколько я себе представляю, сначала делается LEFT JOIN, а потом уже GROUP BY. Из-за этого.
 

amadeus

Новичок
Bitterman
Не мучь себя, не получится так. Значение групповой функции max(`id`) никак не сопоставляется со значением поля `id`, т.е. не будут здесь выбираться значение записи, у которой `id`=max(`id`). Если уж так хочется, чтобы был join сделай так:
SELECT *
FROM `DiscussionPost` inner join (
SELECT max( `id` ) AS `max_id`
FROM `DiscussionPost`
GROUP BY `DiscussionID`
ORDER BY `max_id` DESC
LIMIT 0 , 5
) AS `zlo`
ON `DiscussionPost`.`id` = `zlo`.`max_id`
В некоторых случаях ЗЛО неизбежно.
Быть мне растреляным :(
 

Фанат

oncle terrible
Команда форума
вощзможно, это меня надо расстрелять.
впрочем, если бы у автора была не 4.1 - было бы веселее
 

chira

Новичок
можно сделать без джоинов, на MySQL пример есть ...
Код:
SELECT
	 max(id_msg) id_msg
	,SUBSTRING( MAX( CONCAT(LPAD(id_msg,10,'0'),msg) ), 11) AS `msg`
FROM smf_messages AS m
GROUP BY m.ID_TOPIC
ORDER BY m.ID_TOPIC DESC
LIMIT 0, 5
 
Сверху