За последние 24 часа нас посетил 51341 программист и 1758 роботов. Сейчас ищут 939 программистов ...

Поговорим за JOIN

Тема в разделе "PHP для новичков", создана пользователем Salvat, 5 май 2016.

  1. Salvat

    Salvat Новичок

    С нами с:
    4 мар 2016
    Сообщения:
    101
    Симпатии:
    0
    Имееются таблицы.
    group_name с колонками
    group_id - уникальный номер каждой группы
    group_admin - администратор группы
    есть еще колонки, но они не при чем в данном случае
    имеется таблица
    group_users с колонками
    user_id - это пользователь которые состоит в определенной группе
    group_id - группа в которой состоит пользователь (может быть 1,2,3,4 и принадлежать одному администратору, то есть создателю группы)
    group_admin - администратор группы в которой состоит пользователь

    Почитав мануалы я написал такой запрос, который выводит данные определенного пользователя, который состоит в какой-то группе
    PHP:
    1.  SELECT * FROM group_name INNER JOIN group_users
    2. ON group_name.group_admin=group_users.user_id and group_name.group_id=group_users.group_id WHERE group_users.user_id='1' ;
    Где group_users.user_id='1' - это id пользователя.
    Получаю данные групп, правильно ли я составляю запрос. Думаю, что где-то возможна ошибка. Поясните, пожалуйста.
     
  2. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    ты про дополнительную таблицу не подумал?
    запрос так-то правильный, кроме момента из серии масло-масляное когда ты дважды перечисляешь group_name.group_admin=group_users.user_id
     
  3. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.339
    Симпатии:
    44
    А зачем group_admin в group_users ?
    У юзера уникальный id. По-этому, вывод данных - это просто запрос в таблицу users.
    Мне кажется, вы на русском языке сформулировали задачу криво, а это пол дела.
     
  4. Salvat

    Salvat Новичок

    С нами с:
    4 мар 2016
    Сообщения:
    101
    Симпатии:
    0
    Да вот пока-мись пытаюсь разобраться с JOIN, а там подумаю. Все равно даже если объеденю таблицы, уже объеденил три, тогда будет еще два. Масло-масленное убрал.
    SELECT *
    FROM group_name INNER JOIN group_users
    ON group_name.group_id=group_users.group_id INNER JOIN group_messages
    ON group_name.group_admin=group_messages.group_admin WHERE group_users.user_id='1' ;
    group_messages так же содрежит
    user_id
    group_id
    id - уникальный ид сообщения от администратора группы
    group_admin

    Как я понимаю, JOIN склеивает по колонкам group_name.group_id=group_users.group_id которые с одним id и принадлежат колонке со значением 1 group_users.user_id='1' и так же склеивает group_name.group_admin=group_messages.group_admin где один и тот же администратор написал сообщение, так же с колонкой со значением group_users.user_id='1'
    Далее у меня идут комментарии
    group_wall содержит
    message_id - это уникальный ид с group_messages, сообщения от администратора, в group_messages это просто id
    user_id - так же id пользователя который оставил комментарий к сообщению
    есть еще другие, сообщение, время, эти не столь важны для выборки
    PHP:
    1. $comment_res = mysql_query("SELECT * FROM `group_wall` WHERE message_id='".$rs_info['id']."' and user_id='$id'");
    мне получается необходимо через цикл выводить каждый id комментария к определенному сообщению. Получается примерно так group_messages.messages_id=group_wall.message_id
    Верно или что-то недопонимаю? Или как лучше организовать. Перебрать этот запрос из трех таблиц, затем пустить еще один цикл и выбрать уже данные из group_wall?
    И даже если все 4 запроса объеденю в один, тут может получиться путаница. Так как неоходимо построить диалог. То есть, сначала сообщение администратора, потом уже к нему идут комментарии с group_wall. Как лучше поступить?
    Чтобы знать к какой группе относится пользователь, у админа может быть много групп, допустим, админ имеет id 1 а группы 1,2,3,4 и все относятя к одному администратору группы. Пользователь может относится к одному из админов и состоять в разных группах этого администратора.
    Может быть, сейчас попробовал объяснить более подробно.
     
  5. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.339
    Симпатии:
    44
    Эм, все равно путано.
    Давайте просто - у группы всегда один админ или у группы может быть несколько?
    Если всегда один - достаточно поля admin_id в таблице group_name. Что бы получить - в каких группах наш пользователь - админ, просто делаем SELECT group_id FROM group_name WHERE admin_id = 1;
     
  6. Salvat

    Salvat Новичок

    С нами с:
    4 мар 2016
    Сообщения:
    101
    Симпатии:
    0
    Админ один, он создает группу. Админ пишет сообщение, пользователь который состоит в группе видит эти сообщения, у меня было через циклы все, а @Ganzal сказал, что лучше с помощью JOIN Тут вся тема и там же код который был через циклы. https://php.ru/forum/threads/sortirovka-i-gruppirovka.58328/#post-468775 У меня три разных группы, и в зависимости от настроек пользователя на стене идет отображение сообщений, своих сообщений, от избранных или от групп в которых пользователь состоит. В зависимости от настроек отображаются сообщения, которые мне необходимо комментировать. Весь вопрос с циклами у меня заключился в сортировке, для построения диалогов.
    --- Добавлено ---
    Поясните мне, пожалуйста, вопросы в этом сообщении.
    Поговорим за JOIN
    --- Добавлено ---
    И почему у меня выдает белую страницу, где ошибка? Через phpmyadmin запрос срабатывает на ура.
    PHP:
    1. <?php
    2. include_once('config.php');
    3. $result_join = mysql_query("SELECT *
    4. FROM group_name INNER JOIN group_users
    5. ON group_name.group_id=group_users.group_id INNER JOIN group_messages
    6. ON group_name.group_admin=group_messages.group_admin  WHERE `group_users.user_id`='1' ");
    7.    if(mysql_num_rows($result_join)>0){
    8.      while($row = mysql_fetch_assoc($result_join)){
    9.      echo $row['group_id'];
    10.    }
    11. }
    12. ?>
    --- Добавлено ---
    Код (Text):
    1.  Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in /var/www/html/soc/test.php on line 8
    --- Добавлено ---
    Unknown column 'group_users.user_id' in 'where clause'
    вот такая ошибка почему-то...
    --- Добавлено ---
    Разобрался с ошибкой, вопрос все еще актуален что выше ссылочка, по поводу работы с 4 базами.
     
    #6 Salvat, 5 май 2016
    Последнее редактирование: 5 май 2016
  7. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Может таблицами?
     
  8. Salvat

    Salvat Новичок

    С нами с:
    4 мар 2016
    Сообщения:
    101
    Симпатии:
    0
    @denis01, Да, таблицами. Все таки нужно делать 4 запроса.
    PHP:
    1.  $result_join = mysql_query("SELECT *
    2. FROM group_name INNER JOIN group_users
    3. ON group_name.group_id=group_users.group_id LEFT JOIN group_messages
    4. ON group_name.group_admin=group_messages.group_admin
    5. WHERE group_users.user_id='1'  GROUP BY group_messages.id ASC") or die(mysql_error());
    тут цикл, это выведет сообщения от администратора группы
    потом
    PHP:
    1. $comment_res = mysql_query("SELECT * FROM `group_wall` WHERE message_id='".$rs_info['id']."' and user_id='$id'");
    выводить сообщения под администратором группы, строить диалог, тоже церез цикл и выводить информацию о пользователях. Даже уменьшив кол-во запросов с 5 до 3 мой вопрос все равно актуальным остается. Ибо оптимизация никак не решает мою проблему описанную в данной теме.
    https://php.ru/forum/threads/sortirovka-i-gruppirovka.58328/#post-468775
     
  9. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    (с) за джоин
     
  10. Salvat

    Salvat Новичок

    С нами с:
    4 мар 2016
    Сообщения:
    101
    Симпатии:
    0
    С запросом я разобрался, как совместить все 5 запросов в один.
    PHP:
    1. SELECT *
    2. FROM group_name
    3. INNER JOIN group_users ON group_name.group_id = group_users.group_id
    4. LEFT JOIN group_messages ON group_name.group_admin = group_messages.group_admin
    5. LEFT JOIN users ON group_users.user_id = users.id
    6. LEFT JOIN group_wall ON group_users.user_id = group_wall.user_id
    7. WHERE users.id = '1'
    8. GROUP BY group_wall.id ASC
    Группирую по id комментариев, получаю ответ черз phpmyadmin, выводятся не все нужны мне данные. А именно из некоторых таблиц, значение колонки повторяется, это колонка id. Одно название, значения разные, как мне выбрать с необходимой? Так же в некоторых колонках данные только из одной колонки одной из таблиц. К примеру, есть время у каждого сообщения и оно разное для всех в колонке group_messages, в колонке дата стоит одно и тоже время после слияния. Как тут быть?
     
  11. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Я не читал, ибо дофига слов, но...
    Базы данных создавались как раз для джоинов. Всё вокруг джоинить. См. Нормальная Форма.

    Но когда запаривает джоинить, можно то самое время см. Денормализация. Но это надо осторожненько так, а то всё расползётся.
     
  12. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    @Salvat выбирать нужно не астериском (звездочкой) а перечислением полей. одинаковые имена полей но разные по назначению - можно разрулить алиаласми. ну это если я правильно тебя понял.
     
  13. Salvat

    Salvat Новичок

    С нами с:
    4 мар 2016
    Сообщения:
    101
    Симпатии:
    0
    @Ganzal, Я все равно не могу понять как выбрать мне необходимые данные. Вот код который в данный момент использую.
    PHP:
    1. SELECT
    2.             group_name.group_names,
    3.             group_name.group_admin,
    4.             group_name.first_name_admin,
    5.             group_name.last_name_admin,
    6.             group_name.group_id,
    7.  
    8.            
    9.             group_messages.user_id,
    10.             group_messages.group_messages,
    11.             group_messages.group_admin,
    12.             group_messages.id,
    13.             group_messages.date,
    14.            
    15.             users.avatar,
    16.             users.last_name,
    17.             users.first_name,
    18.            
    19.             group_wall.message,
    20.             group_wall.timedata,
    21.             group_wall.message_id,
    22.            
    23.             group_users.purse_admin,
    24.             group_users.group_admin,
    25.             group_users.price_group,
    26.             group_users.user_id,
    27.             group_users.type_group,
    28.             group_users.vhod_group
    29.            
    30. FROM group_name
    31. LEFT JOIN group_users ON group_name.group_admin = group_users.group_admin // тут склеиваем данные, если колонка в таблице group_name.group_admin равна group_users.group_admin
    32. LEFT JOIN group_messages ON group_name.group_admin = group_messages.group_admin // склеиваем, если group_name.admin равна колонке group_message.group_admin
    33. LEFT JOIN users ON users.id = group_users.user_id // если users.is равна group_users.user_id
    34. LEFT JOIN group_wall ON group_users.user_id = group_wall.user_id // если group_users.user_id равна group_wall.user_id
    35. WHERE users.id = '1' // выбираем по users.id=1
    36. GROUP BY group_wall.id ASC // группируем по id
    В итоге я получаю такой результат
    [​IMG]
    group_id у меня должно быть три результата, 1,2,3, так же ид повторяется 63, и дата время, текст сообщения.
    Вот второй скрин-шот
    [​IMG]
    Тут дата и время комментариев верны, комментарии тоже, id сообщений тоже.
    Я не прошу мне писать код, код сам напишу. Прошу указать на ошибки в моем случае для понимания. Может где я что не так вывожу или какие-то колонки не так склеиваю. Вот это меня интересует.
     
  14. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Фиг знает какова цель и каковы отношения между таблицами, поэтому трудно сказать насколько ты преуспел :)
    Но я таки уверен, что груп бай ты добавил от балды.
     
  15. machetero

    machetero Активный пользователь

    С нами с:
    25 окт 2014
    Сообщения:
    499
    Симпатии:
    21
    Меня смущает ASC без ORDER BY
     
  16. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    @machetero, MySQL допускает такое… как и многие другие некрасивые вещи :)
    сортировка при группировке всё равно присутствует как побочный эффект. а эта добавочка позволяет эксплуатировать побочный эффект.
    --- Добавлено ---
    MySQL также (при дефолтовых настройках) позволяет при группировке указывать лишние поля во фразе SELECT. Хотя спроси автора какие он там значения ожидает увидеть, он не сможет ответить. И MySQL тоже не сможет :D он просто выведет что-нибудь.

    Я потому и считаю, что GROUP BY здесь от балды, потому что ТС заказал ну слишком много полей на вывод. По стандарту, при группировке ты можешь поместить во фразу SELECT только группируемые поля и агрегатные функции от других полей.

    https://php.ru/forum/threads/inner-join-i-count-dlja-trex-tablic.50656/#post-402528
     
  17. Salvat

    Salvat Новичок

    С нами с:
    4 мар 2016
    Сообщения:
    101
    Симпатии:
    0
    GROUP BY добавлен для группировки сообщений иначе я получал очень большое кол-во данных.
    Отсутствовал, все равно остался последний вопрос на который мне так и не ответили...
    Код (Text):
    1. JOIN group_users ON group_name.group_admin = group_users.group_admin // тут склеиваем данные, если колонка в таблице group_name.group_admin равна group_users.group_admin
    2. JOIN group_messages ON group_name.group_admin = group_messages.group_admin // склеиваем, если group_name.admin равна колонке group_message.group_admin
    3. JOIN users ON users.id = group_users.user_id // если users.is равна group_users.user_id
    4.  JOIN group_wall ON group_users.user_id = group_wall.user_id // если group_users.user_id равна group_wall.user_id
    5. WHERE users.id = '1' // выбираем по users.id=1
    Верно ли я понял?
    --- Добавлено ---
    Разобрался, всем спасибо за помощь.