Ознакомьтесь с нашей политикой обработки персональных данных
12:45 

Как будет выглядеть запрос?

Plexx
Кратко о теме. Хочу реализовать систему друзей на сайте.

Имеем таблицу "Друзья"

CREATE TABLE IF NOT EXISTS `users_friends` (
`user_id` int(11) default '0',
`friend_id` int(11) default '0',
`approve` tinyint(1) default '0',
KEY `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;

user_id - id человека кто предлагает дружбу
friend_id - id человека кому предлагаем дружбу
approve - может принимать значение 0 или 1. (Т.е. если 0 то предложение дружить не подтверждено, и собственно если 1 то когда человек кому предложили дружбу подтвердил что хочет дружить)

Имеем так же таблицу юзеров users где находятся все данные. Имя Фамилия и т.д.

Так вот о главном. Все работает замечательно.

Использую простой запрос для вывода друзей у пользователя.

имеем GET переменную $user_id которая равна id тому человеку у которого мы просматриваем друзей

SELECT a.*, b.*
FROM users as a
RIGHT JOIN users_friends as b ON (b.user_id = ".$user_id." or b.friend_id=".$user_id.") and b.approve='1'
WHERE (a.user_id = b.user_id or a.user_id = b.friend_id) and a.user_id!='".$user_id."'

А теперь захотелось возле каждого юзера вывести кнопку дружбы или удаления друга

Голову ломаю как будет выглядеть запрос.. Подскажите пожалуйста.

Если я вывожу у себя на страничке друзей. то соответственно везде будет гореть кнопка удалить друга.
Но если я захожу к другим то там получается тоже будет гореть кнопка удалить друга.. а нужно что бы горела та кнопка которая соответствует моим условиям. Т.е. что бы проверялся каждый юзер на соответствие моей дружбы.

есть глобальная переменная $member[id] которая равна моему id

@темы: MySQL, PHP, Вопросы

Комментарии
2011-02-02 в 13:05 

--==SS==--
Sanctus Satanas
Ну... Приджойнить user_friends под ещё одним алиасом, где вместо $user_id будет {$member[id]}.
Суть в том, что вам нужно определить И то, что юзеры друзья между собой И то, что выбранный юзер друг (или не друг) вам.

2011-02-02 в 13:15 

Plexx
ну да именно так.
вывести друзей у кого нибудь и в тоже время проверить на соответствие друг ли этот человек мне или нет который в списке.

2011-02-02 в 13:17 

Plexx
SS в голове была такая мысль но я запутался что с чем сравнивать(( Подскажите как будет выглядеть запрос

2011-02-02 в 13:37 

--==SS==--
Sanctus Satanas
Если никто раньше не успеет, то чуть попозже. ) Просто у меня сейчас и так есть, над чем голову поломать. )

2011-02-02 в 15:02 

alhames
alhames.ru
DELETE FROM `table` WHERE (`user_id` = '$user_id' AND `friend_id` = '$member[id]') OR (`friend_id` = '$user_id' AND `user_id` = '$member[id]') LIMIT 1
Это удаление

Проверка для списка на дружбу:
SELECT * FROM `table` WHERE (`user_id` = '$member[id]' AND `friend_id`IN( implode( ',', $array_ids ) )) OR (`friend_id` IN( implode( ',', $array_ids ) ) AND `user_id` = '$member[id]')

Что-то не совсем понял проблемы..

2011-02-02 в 15:31 

Plexx
alhames т.е. делать еще один запрос? а как все одним проверить?

2011-02-02 в 16:09 

alhames
alhames.ru
SELECT a.*, b.approve
FROM `users` as a
LEFT JOIN `users_friends` as b
ON ( (b.user_id = a.id AND b.user_id != $member[id] AND b.friend_id = $member[id]) or (b.friend_id=a.id AND b.friend_id != $member[id] AND b.user_id = $member[id]) )
WHERE (a.id = '$member[id]' or a.id IN( implode( ',', $array_ids ) )

При уникальности связей user <-> friend должно вернуть в b.approve NULL если связи нет, 0 - если не подтверждена, 1 - если подтверждена
А вообще надо пробовать - наугад трудно сказать

2011-02-02 в 16:14 

Джей Ди
Всё будет Кока-Кола.
У меня есть подобное решение, когда кто-то просматривает чужой лайтбокс подствечиваются фотографии уже находящиеся в одном из лайтбоксов пользователя.
Запросы генерируются автоматически, сейчас выведу результат...

Тупо выборка, для гостей:
SELECT ... FROM albumsMaps as inLightbox JOIN media ON (media.id = inLightbox.mediaID) WHERE inLightbox.albumID = '2033433' LIMIT 50

Для пользователя:
SELECT DISTINCT ..., albumsMaps.mediaID AS albumed FROM albumsMaps as inLightbox JOIN media ON (media.id = inLightbox.mediaID) LEFT JOIN albumsMaps ON (albumsMaps.ownerID = 1 AND albumsMaps.mediaID = media.id) WHERE inLightbox.albumID = '2033433' LIMIT 50

По факту: тут идет подстветка если картинка в ЛЮБОМ юзерском лайтбоксе: (albumsMaps.ownerID = {userid} AND albumsMaps.mediaID = media.id)
DISTINCT - потому что картинка может быть в нескольких юзерских альбомах.

Т.е. я джоиню таблицу медиа, а не наоборот. Работает шустро.
В случае поиска media (друзей в твоем случае) - аналогично почти, но у меня внешний поисковый демон так что я делаю выборку по id + join albumsMaps.

2011-02-02 в 16:57 

--==SS==--
Sanctus Satanas
У меня вот такая хрень получилась:

SELECT DISTINCT
u.user_name AS userName,
(uf2.user_id IS NOT NULL) AS isOurFriend
FROM
users_friends AS uf1
LEFT JOIN
users AS u
ON
u.user_id IN (uf1.user_id, uf1.friend_id)
LEFT JOIN
users_friends AS uf2
ON
u.user_id IN (uf2.user_id, uf2.friend_id)
AND $myId IN (uf2.user_id, uf2.friend_id)
AND uf2.is_accepted = 1
WHERE
uf1.is_accepted = 1
AND $userId IN (uf1.user_id, uf1.friend_id)

2011-02-02 в 17:32 

Plexx
alhames пробую реализовать пока ваш метод. Потом проработаю другие.
Вопрос в запросе $array_ids что представляет? откуда ее брать?

2011-02-02 в 17:46 

alhames
alhames.ru
$array_ids - это массив id-шников тех пользователей, которых нужно выводить.
Допустим вы зашли на страницу к пользователю X, $array_ids будет содержать перечисление id всех друзей пользователя X.

2011-02-02 в 17:51 

Джей Ди
Всё будет Кока-Кола.
alhames ненене, девид блейн! Хотя с другой стороны для 10-20 друзей сработает быстро.

2011-02-02 в 17:56 

Plexx
alhames Т.е. мне нужно еще одним запросом нужно вытаскивать всех друзей а потом еще одним делать проверку на кнопку дружба?

2011-02-02 в 18:10 

Plexx
Джей Ди ваш запрос совсем не понятен со всякими медиа. Не могли бы вы написать с моими данными. Те что я описал выше.. Я никак не могу прочитать его=)

2011-02-02 в 18:12 

alhames
alhames.ru
Джей Ди ну никто и не выводит более 30 друзей на странице )

Plexx ну да =) Запрос, выбирающий 30 int-ячеек нагрузки не сделает, но зато сделает более наглядной логику программы, т.к. список пользователей - это вовсе не обязательно список друзей, это может быть список гостей вашей страницы и т.д.
Объединять эти запросы мне лень )

2011-02-02 в 18:23 

Plexx
alhames
Ну у меня получается уже три запроса.
Первый тащит 20 друзей у пользователя.
Второй считает общее их кол-во для постраничной навигации
Третий сравнивает на друзей.

Вы считаете это оптимальный вариант будет?

2011-02-02 в 18:30 

alhames
alhames.ru
Plexx ну и что что три, по сути только один будет тяжелый - тот самый что тянет информацию о пользователях и отношениях с $member[id].
В любом случае к таблице связей вам придется обращаться дважды - сначала для выборки друзей user_id, а потом для сверки дружит ли $member[id] с ними.

2011-02-02 в 18:54 

Plexx
alhames
что то я совсем запутался.

Первым запросом я вытаскиваю всех друзей у юзера по $user_id

SELECT a.*
FROM users as a
RIGHT JOIN users_friends as b ON (b.user_id = ".$user_id." or b.friend_id=".$user_id.") and b.approve='1'
WHERE (a.user_id = b.friend_id or a.user_id = b.user_id) a.user_id!='$user_id' DESC LIMIT 10

Затем я циклом их вывожу

while { }

Как же мне из первого запроса получить еще массив id шников юзера если я циклом их вывожу на страничке? Можно ли делать два цикла при одном запросе?

2011-02-02 в 20:08 

Plexx
ну же ребят помогите.

2011-02-02 в 20:11 

alhames
alhames.ru
SELECT `friend_id`, `user_id`
FROM `users_friends`
WHERE (`friend_id` = '$user_id'
OR `user_id` = '$user_id')
AND `approve` = '1'
LIMIT 20

Потом
$array_ids = array();
while( $row = mysql_fetch_assoc($result) ) {
if( $row['friend_id'] == $user_id)
$array_ids[] = $row['user_id'];
else
$array_ids[] = $row['friend_id'];
}

Вот вам массив id-шников.

SELECT COUNT(`id`)
FROM `users_friends`
WHERE (`friend_id` = '$user_id'
OR `user_id` = '$user_id')
AND `approve` = '1'

Вот общее число друзей

SELECT a.*, b.approve
FROM `users` as a
LEFT JOIN `users_friends` as b
ON ( (b.user_id = a.id AND b.user_id != $member[id] AND b.friend_id = $member[id]) or (b.friend_id=a.id AND b.friend_id != $member[id] AND b.user_id = $member[id]) )
WHERE (a.id IN( implode( ',', $array_ids ) )
LIMIT 20

Вот не больше 20 рядов с информацией о пользователях, переданных через массив, а также отношением их к $member[id].

По мне так все элементарно, а вот запрос --==SS==-- меня пугает - даже боюсь вникать ))

2011-02-02 в 20:20 

Plexx
alhames Вот на таком примере мне намного проще анализировать и вникать как строятся запросы и результат. Спасибо большое. Проверю как в работе, позже отпишусь.

2011-02-02 в 22:05 

--==SS==--
Sanctus Satanas
alhames
А я там и накосячил. :-D
Проверенный вариант:

SELECT
u.user_name AS userName,
(uf2.user_id IS NOT NULL) AS isOurFriend
FROM
users_friends AS uf1
JOIN
users AS u
ON
u.user_id IN (uf1.user_id, uf1.friend_id)
AND u.user_id != $userId
LEFT JOIN
users_friends AS uf2
ON
u.user_id IN (uf2.user_id, uf2.friend_id)
AND $myId IN (uf2.user_id, uf2.friend_id)
AND uf2.is_accepted = 1
WHERE
uf1.is_accepted = 1
AND $userId IN (uf1.user_id, uf1.friend_id)


А то иначе первым джоином выбирался ещё и сам искомый юзер, а это уже бред. ) Зато, всё, как любит Plexx — одним запросом. ))

2011-02-02 в 22:50 

--==SS==--
Sanctus Satanas
А… …и ещё надо аналогичную проверку во второй джойн — AND u.user_id != $myId, иначе текущего юзера себя самого много раз выведет. ))

2011-02-03 в 13:17 

Plexx
alhames Все работает отлично... Спасибо за обьяснение как реализовывать те или иные задачи.
--==SS==-- Спасибо и вам за помощь.

   

Сообщество PHP программистов

главная