За последние 24 часа нас посетили 24500 программистов и 1656 роботов. Сейчас ищут 890 программистов ...

INNER JOIN - первое знакомство (нормально так расписал)

Тема в разделе "PHP для новичков", создана пользователем kowapos, 19 мар 2013.

  1. kowapos

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

    С нами с:
    18 янв 2013
    Сообщения:
    120
    Симпатии:
    0
    Уже почти год практикую пхп. Очень нравится, особенно видеть результат. Но я не об этом =D
    Короче.
    Сделал я модуль друзей. И нужно сделать раздел "друзья онлайн". Но для этого нужно воспользоваться такой штукой как INNER JOIN в MySQL.
    Делаю я это впервые. И так, что бы все было ясно, расскажу ка я вам про этих две таблицы которые нужно слепить.
    1. addfriends - сюда записывается вся дружба. Есть поля: added(ид добавленного) и adds (ид добавляющего).
    2. users - тут ничего особенного, инфа про пользователей, нас тут больше интересует поле `line`, в ней находится информация о статусе пользователя в сети (онлайн он или оффлайн).

    в таблице addfriends, ваш id может быть записан в поля как и в `added` так и `adds `, в зависимости кто кого добавляет, вы или вас.

    Что нам нужно:
    для начала нам нужно собрать всех друзей и выбрать кто из них online.
    Основываясь на все выше сказанное, я попробовал составить запрос:

    Код (Text):
    1. SELECT * FROM `addfriends` INNER JOIN `users` ON `users`.`id` = `addfriends`.`adds` and `addfriends`.`added` WHERE `addfriends`.`state` = 'in friends' and (`addfriends`.`adds` = '$myid' or `addfriends`.`added` = '$myid') and `users`.`line` = 'Online' and `users`.`id` != $myid
    длинный он какой-то, но почти правильный.
    Сейчас объясню каждый момент, как я это понимаю.

    Код (Text):
    1. SELECT * FROM `addfriends` INNER JOIN `users`
    выбираем все с наших двух таблиц (кстати, а как выбрать то что нужно? если меня все не устраивает? например в таблице `users` хочу выбрать только имя пользователя и его статус сети)

    Код (Text):
    1. WHERE `addfriends`.`state` = 'in friends' and (`addfriends`.`adds` = '$myid' or `addfriends`.`added` = '$myid') and `users`.`line` = 'Online' and `users`.`id` != $myid
    итак, самое интересное.
    "`addfriends`.`state` = 'in friends'" это статус дружбы, который сейчас равен 'in friends' (это значит в друзьях). Потом.
    and (`addfriends`.`adds` = '$myid' or `addfriends`.`added` = '$myid' как я говорил ранее: id может быть записан в поля как и в `added` так и `adds `, в зависимости кто кого добавляет, вы или вас, по этому мы выбираем где наш id.

    and `users`.`line` = 'Online' - где статус сети юзера равна Online.
    and `users`.`id` != $myid - и выбираем там, где id не равна нашему id, ибо зачем мы сами у себя в списке онлайн?

    и теперь кульминация:
    ON `users`.`id` = `addfriends`.`adds` and `addfriends`.`added` - это я как понял клей уже. тут и проблема. ведь нам нужно и то поле и другое, и там и там могут быть id наших друзей онлайн.

    Надеюсь что я не плохо расписал, и Вам будет не влом мне помочь.
     
  2. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Предпочитаю "направленные" записи о связях.
    а) Саша считает Машу другом, а она его нет: одна запись.
    б) Саша и Маша оба объявили друг друга друзьями (каламбур): две записи.
    При таком раскладе не надо усложнять запрос условием OR. Много записей это не проблема для БД, если запрос использует индексы.
     
  3. kowapos

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

    С нами с:
    18 янв 2013
    Сообщения:
    120
    Симпатии:
    0
    спасибо, но вопрос не в этом был =)
    вопрос: как правильно составить запрос
     
  4. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Код (Text):
    1. SELECT *
    2. FROM `addfriends`
    3. INNER JOIN `users` ON `users`.`id` = `addfriends`.`adds` and `addfriends`.`added`
    4. WHERE
    5.   `addfriends`.`state` = 'in friends' and
    6.   (`addfriends`.`adds` = '$myid' or `addfriends`.`added` = '$myid') and
    7.   `users`.`line` = 'Online' and
    8.   `users`.`id` != $myid
    Так лучше видно ))) И что же мы видим?
    Ты не используешь короткие алиасы, а зря.
    JOIN ... and `addfriends`.`added` и WHERE ... `users`.`id` != $myid лишние. они просто не влияют на результат.
    Твой INNER JOIN по идее должен ограничить все множество users только тем подмножеством, кого ты добавил в друзья. На деле же написано не пойми что. Логика эта размазана по INNER JOIN и WHERE причем в обоих местах есть лишнее.

    INNER JOIN ограничивает результирующий набор только совпадающими записями.
    Без реальных данных, чисто теоретически предложу такое:
    Код (Text):
    1. SELECT u.*
    2. FROM `users` AS u
    3. INNER JOIN `addfriends` AS f
    4.   ON f.`state`='in friends' AND f.`adds`={$myid} AND f.`added`=u.id
    5. WHERE
    6.   `users`.`line` = 'Online'
    Насколько я понимаю здешнюю логику, f.`adds`={$myid} AND f.`added`=u.id должно означать "я добавил этого чувака в друзья".
    Я хочу видеть, тех я кого Я зафрендил! Я их зафрендил чтобы видеть их, они френдят меня чтобы видеть меня. Мне на их потребности насрать. Поэтому условие джойна включает только одно направление и OR здесь нет.

    Из полученной сцепки users и addfriends условие WHERE отфильтрует только тех, кто онлайн.
     
  5. kowapos

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

    С нами с:
    18 янв 2013
    Сообщения:
    120
    Симпатии:
    0
    Unknown column 'u.id' in 'on clause'
    =))

    твой запрос не совсем понят мне =(
    сделал так
    Код (Text):
    1. SELECT DISTINCT u.*
    2. FROM `users` AS u
    3. INNER JOIN `addfriends` AS f
    4.   ON f.`state`='in friends' AND (f.`adds`={$myid} or f.`added`={$myid}) and u.`id`<>$myid
    5. WHERE
    6.   `u`.`line` = 'Online'
    и выводит всех пользователей онлайн, а не моих друзей
     
  6. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Почему-то с distinct у тебя нет ошибки unknown columns. А ведь u.id остался в запросе )))) О чем это говорит? Очевидно косячишь, когда пробуешь запрос.
    Раз нет доверия, не будет и продолжения, ящитаю.
     
  7. kowapos

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

    С нами с:
    18 янв 2013
    Сообщения:
    120
    Симпатии:
    0
    есть доверие, но он не работал, выскакивала та ошибка.
    потом подкоректировал как я вижу это.
    дядь, я просто хочу понять принцип работы, я второй день юзаю этот запрос =( уже все перетыкал

    Добавлено спустя 3 минуты 17 секунд:
    вот, опять вставил твой запрос, ошибка та же Unknown column 'u.id' in 'on clause', плюс после WHERE у тебя там ошибка, вместо `u`.`line` у тебя написано `users`.`line`
     
  8. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    молодец. только это не объясняет ошибку. поностью приведи ее текст, плиз

    Добавлено спустя 1 минуту 39 секунд:
    Код (Text):
    1. SELECT u.*
    2. FROM `users` AS u
    3. INNER JOIN `addfriends` AS f
    4.   ON f.`state`='in friends' AND f.`adds`={$myid} AND f.`added`=u.`id`
    5. WHERE
    6.   u.`line` = 'Online'
    вот можешь такую версию погонять

    Добавлено спустя 1 минуту 22 секунды:
    вообще-то я говорил что я тебе не доверяю, а не наоборот )))
     
  9. kowapos

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

    С нами с:
    18 янв 2013
    Сообщения:
    120
    Симпатии:
    0
    вот ошибка. Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in
    еще не знаешь меня, а уже не доверяешь=))
    выводит пустоту=)) то есть ничего=)
     
  10. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    поменяй слова adds и added местами ))) хз что они должны означать
     
  11. kowapos

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

    С нами с:
    18 янв 2013
    Сообщения:
    120
    Симпатии:
    0
    наверное потому что в f.`adds` не мой ид, а друга. повторюсь, в adds может быть я и и друг, а зависимости от того, кто кого добавил

    Добавлено спустя 40 секунд:
    adds - добавляющий в друзья
    added - добавляемый
    =)
     
  12. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    друг, ты теряешь время. мне неинтересна твоя версия английского. давай быстренько отладим твой запрос

    Добавлено спустя 4 минуты 49 секунд:
    поменял местами, получилось?
     
  13. kowapos

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

    С нами с:
    18 янв 2013
    Сообщения:
    120
    Симпатии:
    0
    дядь. ну при добавлении кого то в друзья, твой id записывается в adds, а id друга в added.
    Код (Text):
    1. SELECT u.*
    2. FROM `users` AS u
    3. INNER JOIN `addfriends` AS f
    4. ON f.`state`='in friends' AND f.`adds`={$myid} AND f.`added`=u.`id`
    5. WHERE
    6. u.`line` = 'Online'
    при таком раскладе, мы выбираем только тех друзей, которых мы добавили. но у нас же есть друзья, которые и нас добавили.

    Добавлено спустя 1 минуту 4 секунды:
    у нас не во всех полях adds = нашему id

    Добавлено спустя 48 секунд:
    а такой вариант не работает
    Код (Text):
    1. (f.`adds`={$myid} or`added`={$myid}
    хотя он и нужен
     
  14. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    видимо нет таких, если прошлый запрос вернул пустое множество ))))

    Добавлено спустя 2 минуты 11 секунд:
    все, чувак, дальше со своими демонами бейся сам.
     
  15. kowapos

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

    С нами с:
    18 янв 2013
    Сообщения:
    120
    Симпатии:
    0
    =( вот так значит #жизньболь
     
  16. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Перечитай топик, осознай, роди свой запрос - стань программистом!