Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Запрос из 3-х таблиц
 
 автор: selma   (16.11.2012 в 02:51)   письмо автору
 
 

Добрый день, поискала похожие темы, кое-что нашлось, но немного не то...

Есть 3 таблицы

forums - список форумов
id_f
name 

threads - темы принадлежащие форумам
id_t
name  
id_forum

messages - сообщения, принадлежащие определенной теме
id_m
name 
id_theme


Нужно 1 запросом сделать выборку, чтобы получилось:
Список форумов | Кол-во тем в каждом форуме | Кол-во сообщений в каждом форуме 


Делаю так:

SELECT f.name, cth FROM forums f
LEFT JOIN (SELECT COUNT(id_t) AS cth, id_f FROM threads GROUP BY id_f  ) 
AS t_counts ON f.id_f = t_counts.id_f


Выводит только форумы и кол-во тем, как усовершенствовать запрос, чтобы выводил еще и кол-во сообщений?

  Ответить  
 
 автор: Sfinks   (16.11.2012 в 08:38)   письмо автору
 
   для: selma   (16.11.2012 в 02:51)
 

/*<?*/
SELECT f.name
     
coalesce(count(*),0)theme_count
     
coalesce(sum(co),0)message_count
FROM forums f
LEFT JOIN threads ON id_f
=id_forum 
LEFT JOIN
SELECT id_theme
                
count(*)co
           FROM messages
           GROUP BY id_theme
)t ON id_theme=id_t
GROUP BY f
.name,id_forum
кажись так. Но чет я спросони не уверен =)

  Ответить  
 
 автор: selma   (16.11.2012 в 08:54)   письмо автору
 
   для: Sfinks   (16.11.2012 в 08:38)
 

theme_count считает не корректно

  Ответить  
 
 автор: Sfinks   (16.11.2012 в 08:56)   письмо автору
 
   для: selma   (16.11.2012 в 08:54)
 

Форумы без тем есть? В них некорректность? Исправьте последнее GROUP BY на
GROUP BY f.name,id_f

  Ответить  
 
 автор: selma   (16.11.2012 в 09:00)   письмо автору
 
   для: Sfinks   (16.11.2012 в 08:56)
 

со скрипом, но работает:) спасибо

Я еще не проверяла, как будет отрабатывать запрос в случае отсутствия тем или сообщений в каком-либо из форумов.

  Ответить  
 
 автор: Sfinks   (16.11.2012 в 09:02)   письмо автору
 
   для: selma   (16.11.2012 в 09:00)
 

"со скрипом" - Что бы это значило..... =(

  Ответить  
 
 автор: selma   (16.11.2012 в 09:10)   письмо автору
 
   для: Sfinks   (16.11.2012 в 09:02)
 

со скрипом, это долгое выполнение:)

  Ответить  
 
 автор: Sfinks   (16.11.2012 в 09:23)   письмо автору
 
   для: selma   (16.11.2012 в 09:10)
 

Полностью.

Во первых изменится условие задачи.
Имя темы, когда весь форум схлопнут в 1 строчку, может быть только одно.
Значит оно должно выбираться по какому-то условию.
name какой именно темы?
- Первой/последней по времени создания?
- Той, в которой было последнее сообщение в пределах данного форума?
- Той, в которой больше всего сообщений?
- Той, в чаще всего встречается буква "я"?
- Той, где меньше матерятся?
Ну и т.п.....

  Ответить  
 
 автор: selma   (16.11.2012 в 09:24)   письмо автору
 
   для: Sfinks   (16.11.2012 в 09:23)
 

- Той, в которой было последнее сообщение в пределах данного форума?


но я в приниципе сделала, добавила поле last_m в тблицу threads и еще один LEFT JOIN в запрос

SELECT f.*, lst, COALESCE(count(*),0) AS ct, COALESCE(sum(co),0) AS cm
FROM forums f
LEFT JOIN threads ON f.id_f=threads.id_f
LEFT JOIN( SELECT id_t, count(*) AS co 
           FROM messages
           GROUP BY id_t ORDER BY id_m
)t ON threads.id_t=t.id_t 
LEFT JOIN( 
SELECT id_f, MAX( last_m ) AS lst
FROM threads
GROUP BY id_f
) AS t_counts ON f.id_f = t_counts.id_f
GROUP BY f.names,f.id_f



И вылез косячок, когда тем нет совсем ни в одном из форумов, показывает 1 причем в каждом форуме

  Ответить  
 
 автор: Sfinks   (16.11.2012 в 09:30)   письмо автору
 
   для: selma   (16.11.2012 в 09:24)
 

Чет вы быстро сообщения редактируете. Вообще не понятно к чему я предыдущий пост написал. =) Наверно я подожду, может передумаете..... =))

> показывает 1 причем в каждом форуме
странно. Покажите дамп таблиц вместе с SHOW CREATE, чтоб я у себя мог попробовать.

  Ответить  
 
 автор: selma   (16.11.2012 в 09:46)   письмо автору
 
   для: Sfinks   (16.11.2012 в 09:30)
 

CREATE TABLE IF NOT EXISTS `forums` (
  `id_f` int(9) NOT NULL AUTO_INCREMENT,
  `names` text NOT NULL,
  PRIMARY KEY (`id_f`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
--
-- Дамп данных таблицы `forums`
--
INSERT INTO `forums` (`id_f`, `names`) VALUES
(1, 'Культура и развлечения'),
(2, 'Вопросы Администрации сайта');

CREATE TABLE IF NOT EXISTS `messages` (
  `id_m` int(9) NOT NULL AUTO_INCREMENT,
  `names` text NOT NULL,
  `id_t` int(9) NOT NULL,
  `times` varchar(10) NOT NULL,
  PRIMARY KEY (`id_m`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `threads` (
  `id_t` int(9) NOT NULL AUTO_INCREMENT,
  `names` text NOT NULL,
  `id_f` int(9) NOT NULL,
  `last_m` int(9) NOT NULL,
  PRIMARY KEY (`id_t`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

  Ответить  
 
 автор: Sfinks   (16.11.2012 в 10:13)   письмо автору
 
   для: selma   (16.11.2012 в 09:46)
 

Да, все верно. Правильно так:
SELECT f.names 
     , count(th.id_f)theme_count 
     , coalesce(sum(co),0)message_count 
FROM forums f 
LEFT JOIN threads th ON f.id_f=th.id_f  
LEFT JOIN( SELECT id_t
                , count(*)co 
           FROM messages 
           GROUP BY id_t
)t ON th.id_t=t.id_t
GROUP BY f.names,f.id_f

Ускорить можно денормализацией.
Если в таблицу threads добавить поле mess_co, то можно избавиться от вложенного подзапроса t.
Для определения темы с последним сообщением лучше не last_m в threads, а сразу last_theme в forums.
times - тип DATETIME или TIMESTAMP лучше использовать. У MySQL довольно богатый набор функций для работы с данными типа дата-время. Не нужно лишать себя этого функционала.

  Ответить  
 
 автор: selma   (16.11.2012 в 10:21)   письмо автору
 
   для: Sfinks   (16.11.2012 в 10:13)
 

Спасибо работает. Структуру поправила, теперь вроде такой запрос:

SELECT f . * , coalesce( SUM( th.mess_co ) , 0 ) AS cm, count( th.id_f ) AS ct
FROM forums f
LEFT JOIN threads th ON f.id_f = th.id_f
GROUP BY f.names, f.id_f


верно?

Уважаемый Sfinks я не могу вас дозваться в icq, вы там бываете?
Есть несколько вопросов

  Ответить  
 
 автор: Valick   (16.11.2012 в 11:50)   письмо автору
 
   для: selma   (16.11.2012 в 10:21)
 

Аська - зло :) Я там тоже по году не бываю
Чем вас форум не устраивает? У Сфинкса уже давно тут прописка :)

  Ответить  
 
 автор: Sfinks   (16.11.2012 в 12:07)   письмо автору
 
   для: selma   (16.11.2012 в 10:21)
 

Верно.
Только у вас th.mess_co может быть null? Думаю нет. Т.е. для тем в которых нет сообщений оно равно 0. Значит coalesce() не нужно.

В аське тоже бываю раз в год по обещанию. Сейчас она у меня даже не установлена.
Лучше задавайте вопросы тут.

  Ответить  
 
 автор: selma   (16.11.2012 в 12:18)   письмо автору
 
   для: Sfinks   (16.11.2012 в 12:07)
 

По факту, я согласна с вами, аська - зло. Но я считаю, что здесь, на форуме, все черезчур уж обезличено. Надо все равно приват-контакт сделать. Вдруг человек захочет обратиться к кому-либо за "фриланс помощью"?

  Ответить  
 
 автор: Sfinks   (16.11.2012 в 13:38)   письмо автору
 
   для: selma   (16.11.2012 в 12:18)
 

Для этого в каждом сообщении есть ссылка "письмо автору"

  Ответить  
 
 автор: selma   (16.11.2012 в 17:01)   письмо автору
 
   для: Sfinks   (16.11.2012 в 13:38)
 

Когда-то уже обсуждалось, что эта ссылка не работает:(
Но я попробую снова:)

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования