SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 04.02.2010 17:42:05

alexxx
Участник
Зарегистрирован: 03.02.2010
Сообщений: 11

Сложный запрос

Есть таблицы _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)

Неактивен

 

#2 04.02.2010 17:57:58

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Сложный запрос

В вашем запросе написано - выбрать из таблицы _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) такого поля нет.

В данном случае нужно сначала объединить таблицы, а потом уже выбирать.

А ещё лучше изначально хранить интересующую вас информацию. Она хоть и является избыточной, но проще вносить изменения при каждом новом посте, чем выполнять сложный запрос при каждом просмотре.

Неактивен

 

#3 04.02.2010 18:03:29

alexxx
Участник
Зарегистрирован: 03.02.2010
Сообщений: 11

Re: Сложный запрос

Данный сложный запрос значительно увеличит время выборки?

>В данном случае нужно сначала объединить таблицы, а потом уже выбирать.
И честно говоря не могу понять как мне это сделать

Отредактированно alexxx (04.02.2010 18:07:08)

Неактивен

 

#4 04.02.2010 18:25:58

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Сложный запрос

alexxx написал:

Данный сложный запрос значительно увеличит время выборки?

Да. И при этом он будет выполняться гораздо чаще, чем добавляются новые посты. С точки зрения нагрузки на сервер выгодней хранить избыточную информацию, обновляя её при добавлении поста. Собственно так устроены все стандартные форумы и вы легко можете в этом убедиться, установив его и посмотрев структуру базы.

alexxx написал:

И честно говоря не могу понять как мне это сделать

SELECT .. FROM _forum_topics a LEFT JOIN _forum_messages b ON b.TopicId=a.Id ..
Если не можете сразу написать сложный запрос, делайте это по частям - объедините таблицы, посмотрите на выдачу, подумайте как извлечь кол-во сообщений из этой выборки, потом дату, и т.д. постепенно усложняя запрос.

Неактивен

 

#5 04.02.2010 18:31:03

alexxx
Участник
Зарегистрирован: 03.02.2010
Сообщений: 11

Re: Сложный запрос

>SELECT .. FROM _forum_topics a LEFT JOIN _forum_messages b ON b.TopicId=a.Id

В этом случае будут возвращены все сообщение в данной теме, а меня интересует одно последнее

>Да. И при этом он будет выполняться гораздо чаще, чем добавляются новые посты. С точки зрения нагрузки на сервер выгодней хранить избыточную информацию, обновляя её при добавлении поста. Собственно так устроены все стандартные форумы и вы легко можете в этом убедиться, установив его и посмотрев структуру базы.

Изначатльно я так и хотел сделать, но пошел по сложному пути, чтобы разобраться в запросах данного типа

Отредактированно alexxx (04.02.2010 18:32:45)

Неактивен

 

#6 04.02.2010 18:39:59

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Сложный запрос

В этом случае будут возвращены все сообщения для каждой из тем или указано null если тема не имеет сообщение (последнего наверное быть не может, поэтому left join в данном случае избыточен и подойдет просто join). Теперь напрашивается провести группировку по темам, т.е. .. GROUP BY a.Id

Лучший способ разобраться http://dev.mysql.com/doc/refman/5.0/en/join.html

Неактивен

 

#7 04.02.2010 19:21:15

alexxx
Участник
Зарегистрирован: 03.02.2010
Сообщений: 11

Re: Сложный запрос

С GROUP BY все встало на свои места. Спасибо

Неактивен

 

#8 04.02.2010 20:03:24

alexxx
Участник
Зарегистрирован: 03.02.2010
Сообщений: 11

Re: Сложный запрос

И вот еще один вопрос здесь, чтобы новую тему не создавать
Можно ли как то объединить два независимых запроса INSERT + UPDATE в один?

Неактивен

 

#9 04.02.2010 20:14:09

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Сложный запрос

Независимых — нельзя. Да и зачем?

Зависимых — можно. INSERT ON DUPLICATE KEY UPDATE — наиболее популярный
вариант smile

Неактивен

 

#10 04.02.2010 20:15:45

alexxx
Участник
Зарегистрирован: 03.02.2010
Сообщений: 11

Re: Сложный запрос

Один запрос насколько я понимаю выполнится быстрее чем два по отдельности
Хотя бы потому, что сократится время на передачу запроса от web к mysql серверу

Отредактированно alexxx (04.02.2010 20:45:42)

Неактивен

 

#11 04.02.2010 20:50:37

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Сложный запрос

Теоретически — да. Практически — Вы этого не заметите ни при какой нагрузке smile
А вообще, преждевременная оптимизация — корень зла.

Неактивен

 

#12 04.02.2010 20:51:28

alexxx
Участник
Зарегистрирован: 03.02.2010
Сообщений: 11

Re: Сложный запрос

Мне на будущее интересно. Согласен сейчас в оптимизации смысла нет

Неактивен

 

#13 05.02.2010 11:17:23

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Сложный запрос

На будущее: PHP вносит куда большие лаги в процессе работы, чем два запроса,
выполненные последовательно. Раз в тысячу большие :-)

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson