SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 21.07.2010 13:07:21

maxtor
Участник
Зарегистрирован: 21.07.2010
Сообщений: 20

Запрос выборки пользователей с проверкой на дружбу

2 таблицы: пользователи (friends) и друзья (users)

Структура таблицы друзей:

Код:

CREATE TABLE IF NOT EXISTS `friends` (
  `user1` int(10) unsigned NOT NULL default '0',
  `user2` int(10) unsigned NOT NULL default '0',
  `status` enum('pending','active') NOT NULL default 'pending',
  `from` int(11) NOT NULL default '0',
  `date` datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY  (`user1`,`user2`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;

В таблицу пользователи заносятся так: в user1 - минимальный id среди друзей, в user2 - максимальный
user1 = min($user1, $user2), user2 = max($user1, $user2)
Дабы исключить повторений

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

Код:

SELECT
    u.*,
    EXISTS(    SELECT *
            FROM friends
            WHERE
                (    user1 = $my_id
                    AND user2 = u.id
                ) OR (
                    user1 = u.id
                    AND user2 = $my_id
                )
                AND `status` = 'active'
            ) AS friend
FROM
    users AS u
ORDER BY username

Из-за:

Код:

(    user1 = $my_id
    AND user2 = u.id
) OR (
    user1 = u.id
    AND user2 = $my_id
)

Запрос работает не оправданно долго. Индекс в под запросе не используется...
Без дополнительного OR:

Код:

WHERE
    user1 = $my_id
    AND user2 = u.id
    AND `status` = 'active'

включается индекс и запрос выполняется быстро. Но в таком виде не известно какой параметр меньше $my_id или u.id что бы правильно присвоить их полям user1 и user2

Подскажите как мне оптимизировать запрос либо структуру таблицы друзей...

Отредактированно maxtor (21.07.2010 13:09:39)

Неактивен

 

#2 21.07.2010 13:49:22

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Запрос выборки пользователей с проверкой на дружбу

Есть несколько мыслей.

1. А почему у Вас дружба только обоюдная? smile
2. Если у Вас такие странные правила подружения, то почему бы
не воспользоваться знанием id1 < id2 и не делать два простых
запроса, которые у Вас работают, на соответствующих поддиапа-
зонах id?
3. Зачем нужен exists, когда достаточно сделать LEFT JOIN?

Неактивен

 

#3 21.07.2010 13:57:59

maxtor
Участник
Зарегистрирован: 21.07.2010
Сообщений: 20

Re: Запрос выборки пользователей с проверкой на дружбу

paulus, ну почему странные? Как во всех социалках: отправляешь запрос на дружбу, если второй подтверждает, то он появляется в твоем списке друзей, а ты в его.
На счет id1 < id2 не совсем понял, как это можно применить. Можете показать это в запросе?

Неактивен

 

#4 21.07.2010 15:17:41

maxtor
Участник
Зарегистрирован: 21.07.2010
Сообщений: 20

Re: Запрос выборки пользователей с проверкой на дружбу

Понял, что вы имели введу:

Код:

user1 = IF ($my_id < u.id, 1, u.id)
AND user2 = IF($my_id > u.id, 1, u.id)
AND `status` = 'active'

Да, индексы подключились, запрос выполняется быстро. Спасибо

Неактивен

 

#5 21.07.2010 15:55:38

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Запрос выборки пользователей с проверкой на дружбу

Странно, что тут работает smile Я имел в виду SELECT … UNION SELECT ….

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson