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

Форум MySQL

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

 

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

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

тема: Сложная выборка
 
 автор: 1prom   (16.06.2009 в 21:13)   письмо автору
 
 

В таблице Friends есть такие поля:

Friend1 (int) Friend2 (int) is_friend (int)

Коля Маша 2
Вика Коля 2
Маша Женя 2
Дима Маша 2
Артем Маша 2
Коля Вася 1

У Коли есть 2 друга: Маша и Вика
У Маши есть 4 друга: Коля, Женя, Дима, Артем
Нужно выбрать друзей и друзей друзей Коли: Маша, Вика, Женя, Дима, Артем.

Подскажите, пожалуйста, как построить такой запрос.

  Ответить  
 
 автор: Trianon   (16.06.2009 в 21:30)   письмо автору
 
   для: 1prom   (16.06.2009 в 21:13)
 

Если это рабочий вопрос ( а не учебный) таблицу следует перепроектировать. Она явно не нормализована.
Раскройте всю правду о Васе.

>Friend1 (int) Friend2 (int) is_friend (int)
и вправду int...

  Ответить  
 
 автор: 1prom   (16.06.2009 в 21:42)   письмо автору
 
   для: Trianon   (16.06.2009 в 21:30)
 

Не знаю даже как перепроектировать...

У каждого имени есть свой номер... я для простоты имена поставил.
а Вася он не в друзьях... он как бы еще это не подтвердил от Коли, если подтвердит там будет двоечка :))

  Ответить  
 
 автор: Trianon   (16.06.2009 в 22:08)   письмо автору
 
   для: 1prom   (16.06.2009 в 21:42)
 

ну вот Вы пишете "У Маши есть 4 друга: Коля, Женя, Дима, Артем"
а строк с Машей во второй колонке только три. из четырех
а в первой так и вообще одна.

  Ответить  
 
 автор: 1prom   (17.06.2009 в 00:42)   письмо автору
 
   для: Trianon   (16.06.2009 в 22:08)
 

все правильно, просто Маша добавила в друзья только Женю с его согласия, остальные добавляли ее в друзья с ее согласия. В итоге 4 друга.

Я не знаю просто как мне правильно скомбинировать запрос...

  Ответить  
 
 автор: 1prom   (17.06.2009 в 22:11)   письмо автору
 
   для: Trianon   (16.06.2009 в 22:08)
 

Trianon, если Вы не подскажете, вряд ли кто-то поможет ))

  Ответить  
 
 автор: Trianon   (17.06.2009 в 22:25)   письмо автору
 
   для: 1prom   (17.06.2009 в 22:11)
 

Я уже сказал.
Строк с Машей должно быть восемь.

Отношение "друзья" не является симметричным даже в реальной жизни, что уж тут про sql говорить...

  Ответить  
 
 автор: 1prom   (17.06.2009 в 22:37)   письмо автору
 
   для: Trianon   (17.06.2009 в 22:25)
 

но ведь это лишние записи БД, ладно, проехали,

теперь допустимв нас есть 8 строчек с Машей и 4 с Колей. как же запрос составить??

  Ответить  
 
 автор: Trianon   (17.06.2009 в 23:44)   письмо автору
 
   для: 1prom   (17.06.2009 в 22:37)
 

Таблица friend_of(user_id, friend_id)

Запрос показывающий друзей Маши
SELECT friend_id 
  FROM friend_of  
  WHERE user_id = $masha


Запрос показывающий друзей друзей Маши
SELECT f1.friend_id 
  FROM friend_of f1  
    JOIN friend_of f2 ON f1.user_id = f2.friend_id 
  WHERE f2.user_id = $masha

  Ответить  
 
 автор: 345386876   (27.06.2009 в 02:32)
 
   для: Trianon   (17.06.2009 в 23:44)
 

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

Скажем, какой-то человек пытается добавить меня в друзья. Таким образом добавляется запись
(user_id, friend_id) = (id_этого_пользователя, мой_id)

В свою очередь я должен добавить запись
(user_id, friend_id) = (мой_id, id_этого_пользователя)

, ... чтобы он считался подтвержденным другом.

Было бы достаточно просто, если бы в MySQL был FULL OUTER JOIN. Его, кажется, нет. Чо делать?

  Ответить  
 
 автор: Trianon   (27.06.2009 в 02:49)   письмо автору
 
   для: 345386876   (27.06.2009 в 02:32)
 

Зарегистрируйтесь, пожалуйста.

  Ответить  
 
 автор: 32423423   (27.06.2009 в 02:54)   письмо автору
 
   для: Trianon   (27.06.2009 в 02:49)
 

Я неправильно вопрос задал. Вычислить неподтвержденных я знаю как. Как можно достать всех друзуй - неподтверженных и подтвержденных одновременно? То есть какая-то запись может быть у меня, но не быть соответвующией у друга. Аналогично может наооборот.

  Ответить  
 
 автор: Trianon   (27.06.2009 в 03:05)   письмо автору
 
   для: 32423423   (27.06.2009 в 02:54)
 

Все мои друзья (и подтвержденные и неподтвержденные) характеризуются friend_of.user_id = $my_id

Все Ваши друзья (и подтвержденные и неподтвержденные) характеризуются friend_of.user_id = $your_id

Еще раз . Отношения могут быть рефлексивными , симметричными , транзитивными

Являться другом - отношение нерефлексивное, несимметричное и нетранзитивное.
Поскольку оно несимметричное, прямая и встречная запись в таблице означают разные вещи. Совсем разные.


Да, для симметричных отношений Full outer join могло бы пригодиться.
Но явная декларация таких отношений (без развертывания в пару независимых) приводит к денормализации схемы, а значит к изрядному усложнению логики как запросов, так и приложения.
Т.е. на мой взгляд - ну его нафик.

PS. Спасибо за понимание. Я про логин.

  Ответить  
 
 автор: 32423423   (27.06.2009 в 03:11)   письмо автору
 
   для: Trianon   (27.06.2009 в 03:05)
 

В моём случае отношение "есть друг" симметричное, антирефлексивное, нетранзитивное. Какая организация предпочтительней-то?..

Из Вашего поста я понимаю так, что симметричность несовместима с организацией, что Вы предложили топикстартеру. А парочка полей "друг_1", "друг_2" приводит к денормализации схемы, а значит к изрядному усложнению логики как запросов.
Выходит, что реализовать симметричность можно только "через задницу"?

В принципе, я могу и парочку полей использовать. Уже так делал ("через задницу"). Просто неудобно. Потому что через задницу.

  Ответить  
 
 автор: Trianon   (27.06.2009 в 03:25)   письмо автору
 
   для: 32423423   (27.06.2009 в 03:11)
 

по-моему, через задницу будет как раз наоборот устраивать всякое
(SELECT friend_id AS fr FROM friend_of WHERE user_id = $my_id)
UNION 
(SELECT user_id AS fr FROM friend_of WHERE friend_id = $my_id)

  Ответить  
 
 автор: 3563649   (27.06.2009 в 03:39)
 
   для: Trianon   (27.06.2009 в 03:25)
 

Вот вокруг этого и вертелся! Мне просто необходимо было еще отсеживать кто подал заявку, поэтому почему-то сразу отбрасывал UNION.
Сейчас, думаю, добавить ", -1" и ", 1" к списку выборки, тогда если <0, то я подаю, если ==0, то мы друзья, если >0, то он подает.
Спасибо.
P.S. Я уже с мобилки, поэтому уж извините.

  Ответить  
 
 автор: 396465640   (27.06.2009 в 03:44)
 
   для: 3563649   (27.06.2009 в 03:39)
 

Я говорю о SUM + GROUP BY user_id!

P.S. Т.к. я с мобилки то точно не уверен: в GROUP BY надо вроде будет писать именно название столбца из первого Select'а

  Ответить  
 
 автор: 32423423   (27.06.2009 в 12:59)   письмо автору
 
   для: 396465640   (27.06.2009 в 03:44)
 

Don't worry - be happy!

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

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