Задавайте вопросы, мы ответим
Вы не зашли.
Есть таблицы _forum_topics - список тем форума, _forum_messages - сообщения, _users - пользователи
Нужно одним запросом получить список тем, посчитать количество сообщений в каждой теме, получить дату последнего сообщения каждой темы и получить имя пользователя оставившего это последнее сообщение
Я пробую сделать так:
SELECT a.Id, a.Name,
(SELECT Count(*) FROM _forum_messages WHERE TopicId=a.Id) as Counter,
(SELECT b.Date FROM _forum_messages b WHERE b.TopicId=a.Id ORDER BY b.Date DESC LIMIT 1) as Date,
(SELECT CONCAT(c.FirstName,' ',c.LastName) FROM _users c WHERE c.UserId=b.UserId) as UserName
FROM _forum_topics a
Получаю Unknown column 'b.UserId' in 'where clause
Если убрать (SELECT CONCAT(c.FirstName,' ',c.LastName) FROM _users c WHERE c.UserId=b.UserId) as UserName
Все работает
Отредактированно alexxx (04.02.2010 17:45:47)
Неактивен
В вашем запросе написано - выбрать из таблицы _forum_topics a в числе прочего (SELECT CONCAT(c.FirstName,' ',c.LastName) FROM _users c WHERE c.UserId=b.UserId) as UserName. Логично, что он ругается на неопределенное поле b.UserId, так как в таблицах из которых вы выбираете (_forum_topics a и _users c) такого поля нет.
В данном случае нужно сначала объединить таблицы, а потом уже выбирать.
А ещё лучше изначально хранить интересующую вас информацию. Она хоть и является избыточной, но проще вносить изменения при каждом новом посте, чем выполнять сложный запрос при каждом просмотре.
Неактивен
Данный сложный запрос значительно увеличит время выборки?
>В данном случае нужно сначала объединить таблицы, а потом уже выбирать.
И честно говоря не могу понять как мне это сделать
Отредактированно alexxx (04.02.2010 18:07:08)
Неактивен
alexxx написал:
Данный сложный запрос значительно увеличит время выборки?
Да. И при этом он будет выполняться гораздо чаще, чем добавляются новые посты. С точки зрения нагрузки на сервер выгодней хранить избыточную информацию, обновляя её при добавлении поста. Собственно так устроены все стандартные форумы и вы легко можете в этом убедиться, установив его и посмотрев структуру базы.
alexxx написал:
И честно говоря не могу понять как мне это сделать
SELECT .. FROM _forum_topics a LEFT JOIN _forum_messages b ON b.TopicId=a.Id ..
Если не можете сразу написать сложный запрос, делайте это по частям - объедините таблицы, посмотрите на выдачу, подумайте как извлечь кол-во сообщений из этой выборки, потом дату, и т.д. постепенно усложняя запрос.
Неактивен
>SELECT .. FROM _forum_topics a LEFT JOIN _forum_messages b ON b.TopicId=a.Id
В этом случае будут возвращены все сообщение в данной теме, а меня интересует одно последнее
>Да. И при этом он будет выполняться гораздо чаще, чем добавляются новые посты. С точки зрения нагрузки на сервер выгодней хранить избыточную информацию, обновляя её при добавлении поста. Собственно так устроены все стандартные форумы и вы легко можете в этом убедиться, установив его и посмотрев структуру базы.
Изначатльно я так и хотел сделать, но пошел по сложному пути, чтобы разобраться в запросах данного типа
Отредактированно alexxx (04.02.2010 18:32:45)
Неактивен
В этом случае будут возвращены все сообщения для каждой из тем или указано null если тема не имеет сообщение (последнего наверное быть не может, поэтому left join в данном случае избыточен и подойдет просто join). Теперь напрашивается провести группировку по темам, т.е. .. GROUP BY a.Id
Лучший способ разобраться http://dev.mysql.com/doc/refman/5.0/en/join.html
Неактивен
С GROUP BY все встало на свои места. Спасибо
Неактивен
И вот еще один вопрос здесь, чтобы новую тему не создавать
Можно ли как то объединить два независимых запроса INSERT + UPDATE в один?
Неактивен
Независимых — нельзя. Да и зачем?
Зависимых — можно. INSERT ON DUPLICATE KEY UPDATE — наиболее популярный
вариант
Неактивен
Один запрос насколько я понимаю выполнится быстрее чем два по отдельности
Хотя бы потому, что сократится время на передачу запроса от web к mysql серверу
Отредактированно alexxx (04.02.2010 20:45:42)
Неактивен
Теоретически — да. Практически — Вы этого не заметите ни при какой нагрузке
А вообще, преждевременная оптимизация — корень зла.
Неактивен
Мне на будущее интересно. Согласен сейчас в оптимизации смысла нет
Неактивен
На будущее: PHP вносит куда большие лаги в процессе работы, чем два запроса,
выполненные последовательно. Раз в тысячу большие :-)
Неактивен