Помогите составить запрос (три таблицы - один запрос) MySQL + PHP

Тема в разделе "Базы данных", создана пользователем Voshal, 6 сен 2010.

Статус темы:
Закрыта.
Модераторы: latteo
  1. Voshal

    Voshal Мизантроп

    Регистр.:
    30 мар 2009
    Сообщения:
    286
    Симпатии:
    108
    Три таблицы - один запрос (MySQL + PHP)

    Приветствую.
    Код:
    CREATE TABLE `forums` (
      `id_forum` int(5) NOT NULL auto_increment,
      `name` varchar(255) NOT NULL,
      PRIMARY KEY  (`id`)
    ) TYPE=MyISAM AUTO_INCREMENT=1 ;
    CREATE TABLE `thems` (
      `id_theme` int(5) NOT NULL auto_increment,
      `id_forum` int (5) NOT NULL,
      PRIMARY KEY  (`id`)
    ) TYPE=MyISAM AUTO_INCREMENT=1 ;
    CREATE TABLE `posts` (
      `id_post` int(5) NOT NULL auto_increment,
      `id_theme` int (5) NOT NULL,
      PRIMARY KEY  (`id`)
    ) TYPE=MyISAM AUTO_INCREMENT=1 ;
    Имеются три таблицы.
    Код:
    [B]forums[/B]
      id_forum //id Форума
      name     //Название раздела
    ------------------------------
    [B]thems[/B]
      id_theme //id темы
      id_forum //id раздела, которому пренадлежит тема
    ------------------------------
    [B]posts[/B]
      id_post  //id поста
      id_theme //id темы, которой принадлежит пост
    В таблице forums 4 строки
    Код:
    [B]id_forum[/B]  [B]name[/B]
    1         Флуд
    2         Компьютеры
    3         Отдых
    4         Купля/Продажа
    
    Код:
    [B]id_theme[/B]  [B]id_forum[/B]
    1         2
    2         2
    3         3
    4         1
    5         3
    6         2
    
    Код:
    [B]id_post[/B]   [B]id_theme[/B]
    1         1
    2         2
    3         2
    4         3
    5         2
    6         4
    7         5
    8         6
    9         5
    
    Необходимо задать 1 запрос mysql, чтобы был такой вывод (причем должны выводиться даже те разделы, в которых нет тем:(
    id Форума - Название форума - количество тем в данном разделе / количество постов в данном разделе
    id Форума - Название форума - количество тем в данном разделе / количество постов в данном разделе
    id Форума - Название форума - количество тем в данном разделе / количество постов в данном разделе
    id Форума - Название форума - количество тем в данном разделе / количество постов в данном разделе
    То есть вывод должен быть такой
    HTML:
    1 - Флуд - 1 / 1
    2 - Компьютеы - 3 / 5
    3 - Отдых - 2 / 3
    4 - Купля/Продажа - 0 / 0
    Одним запросом смог вывести только
    id Форума - Название форума - количество тем в данном разделе
    id Форума - Название форума - количество тем в данном разделе
    id Форума - Название форума - количество тем в данном разделе
    то есть
    HTML:
    1 - Флуд - 1
    2 - Компьютеы - 3
    3 - Отдых - 2
    1. Вывелось только три строки, разделы, в которых есть темы.
    2. Нет вывода количества постов в данном разделе
    Запрос был такой
    PHP:
    $ath mysql_query("SELECT forums.id_forum, forums.name, count( thems.id_theme ) AS temy
    FROM forums, thems
    WHERE thems.id_forum = forums.id_forum
    GROUP BY forums.id_forum;"
    );
      while(
    $forums mysql_fetch_array($ath))
      {
        echo 
    "$forums['id_forum'] - $forums['name'] - $forums['temy']";
      }
    Прошу помощи в реализации. Заранее благодарю.
     
  2. malibu

    malibu Создатель

    Регистр.:
    8 июл 2009
    Сообщения:
    20
    Симпатии:
    9
    PHP:
    $ath mysql_query("SELECT 
        forums.id_forum, 
        forums.name, 
        (select count(*) from thems tm where tm.id_forum = forums.id_forum) AS temy,
        (
            select
                count(*)
            from
                thems tm ,
                            posts p
            where
                tm.id_forum = forums.id_forum and
                p.id_theme = tm.id_theme
        ) AS post
    FROM 
        forums"
    );
      while(
    $forums mysql_fetch_array($ath))
      {
        echo 
    "$forums['id_forum'] - $forums['name'] - $forums['temy'] - $forums['post']";
      }  
    Добавлено через 25 минут
    Еще один вариант:

    PHP:
    $ath mysql_query("SELECT
        f.id_forum,
        f.name,
        count(t.id_theme) AS temy,
        count(p.id_post) AS post
    FROM
        forums f
    LEFT JOIN  
        thems t ON t.id_forum = f.id_forum
    LEFT JOIN    
        posts p ON p.id_theme = t.id_theme
    GROUP BY
      f.id_forum"
    );

      while(
    $forums mysql_fetch_array($ath))
      {
        echo 
    "$forums['id_forum'] - $forums['name'] - $forums['temy'] - $forums['post']";
      }  
     
    Voshal нравится это.
  3. Voshal

    Voshal Мизантроп

    Регистр.:
    30 мар 2009
    Сообщения:
    286
    Симпатии:
    108
    Спасибо большое :)
    Первый запрос выдает то что нужно.
    Код:
    1 - Флуд - 1 / 1
    2 - Компьютеы - 3 / 5
    3 - Отдых - 2 / 3
    4 - Купля/Продажа - 0 / 0
    
    Второй запрос выдает немного неверно (количество тем равно количеству постов), то есть
    Код:
    1 - Флуд - 1 / 1
    2 - Компьютеы - 5 / 5
    3 - Отдых - 3 / 3
    4 - Купля/Продажа - 0 / 0
    
    Немного изменил первый запрос, вместо * поставил 1
    Код:
    SELECT forums.id_forum, forums.name,
        (SELECT COUNT(1) FROM thems tm WHERE tm.id_forum = forums.id_forum) AS temy,
        (SELECT COUNT(1) FROM thems tm, posts p WHERE tm.id_forum = forums.id_forum AND p.id_theme = tm.id_theme) AS post
        FROM forums
    
     
  4. malibu

    malibu Создатель

    Регистр.:
    8 июл 2009
    Сообщения:
    20
    Симпатии:
    9
    Да, немного затупил, во втором варианте надо
    PHP:
    count(t.id_theme) AS temy,
    count(p.id_post) AS post 
    заменить на
    PHP:
    count(distinct t.id_theme) AS temy,
    count(distinct p.id_post) AS post 
     
    Voshal нравится это.
  5. Voshal

    Voshal Мизантроп

    Регистр.:
    30 мар 2009
    Сообщения:
    286
    Симпатии:
    108
    Спасибо. Второй запрос шустрее работает. Это хорошо.

    Код:
    Первый запрос
    Showing rows 0 - 4 (5 total, Query took 0.0023 sec)
    
    Второй запрос
    Showing rows 0 - 4 (5 total, Query took 0.0010 sec)
     
Статус темы:
Закрыта.