Проблемы с таблицей контактов - PullRequest
1 голос
/ 05 июля 2011

У меня есть что-то похожее на таблицу друзей.Его называют contacts.

  • user_id - это идентификатор пользователя, который похож на владельца этого контакта,
  • contact_id - это идентификатор пользователя, который дружит с user_id;

Вторая таблица называется events.Он имеет:

  • user_id - это ID пользователя, который создал это событие.

Мне нужно выбрать события, созданные моими друзьями.Поэтому, если у меня есть Джон и Анна в моем списке контактов ... Мне нужно отобразить их события.

Вот решение:

SELECT `bio_community_events`.`id`, 
       `bio_community_events`.`begin_on`, 
       `bio_community_events`.`name`
  FROM `bio_community_events`
  JOIN `bio_contacts` ON (`bio_contacts`.`contact_id` = `bio_community_events`.`user_id`)
 WHERE `bio_contacts`.`user_id` = '33'

То есть, мой идентификатор 33.Это дает мне события моих друзей.И тут возникает проблема ...

Бывают ситуации, когда я не тот, кто вступает в контакт с моим другом.Наоборот, Анна сделала это.Этот запрос просто игнорирует это и не отображает результаты для Анны.

Ответы [ 3 ]

2 голосов
/ 05 июля 2011
SELECT `bio_community_events`.`id`, 
       `bio_community_events`.`begin_on`, 
       `bio_community_events`.`name`
  FROM `bio_community_events`
  JOIN `bio_contacts`
    ON (`bio_contacts`.`contact_id` = `bio_community_events`.`user_id`)
 WHERE `bio_contacts`.`user_id` = '33'

UNION ALL                                 --- or UNION if this gives you
                                          --- duplicate row
SELECT `bio_community_events`.`id`, 
       `bio_community_events`.`begin_on`, 
       `bio_community_events`.`name`
  FROM `bio_community_events`
  JOIN `bio_contacts` 
    ON (`bio_contacts`.`user_id` = `bio_community_events`.`user_id`)
 WHERE `bio_contacts`.`contact_id` = '33'

или как это:

SELECT `bio_community_events`.`id`, 
       `bio_community_events`.`begin_on`, 
       `bio_community_events`.`name`
  FROM `bio_community_events`
  JOIN 
    ( SELECT `bio_contacts`.`contact_id` AS id
        FROM `bio_contacts`
       WHERE `bio_contacts`.`user_id` = '33'
    UNION ALL                               
      SELECT `bio_contacts`.`user_id` AS id 
        FROM `bio_contacts`                                  
       WHERE `bio_contacts`.`contact_id` = '33'
    ) AS un
    ON ( un.id = `bio_community_events`.`user_id`)

Чтобы установить предел для всех возвращаемых строк в примере # 1, используйте:

( SELECT ... )
UNION ALL
( SELECT ... )

ORDER BY ?        --- optional
LIMIT x ;

Использование ORDER BY тамможет быть довольно дорогостоящим в таком запросе.Вы также можете иметь этот (другой) запрос, который может использовать индексы:

( SELECT ... 
  ORDER BY ?
  LIMIT a
)
UNION ALL
( SELECT ...
  ORDER BY ?
  LIMIT b
)

LIMIT x ;         --- with or without this LIMIT

Другой способ решения исходной проблемы - использовать EXISTS:

SELECT `bio_community_events`.`id`, 
       `bio_community_events`.`begin_on`, 
       `bio_community_events`.`name`
  FROM `bio_community_events`
  WHERE EXISTS  
      ( SELECT *
          FROM `bio_contacts`
         WHERE `bio_contacts`.`user_id` = '33'
           AND `bio_contacts`.`contact_id` = `bio_community_events`.`user_id`
      )
     OR EXISTS
      ( SELECT *
          FROM `bio_contacts`
         WHERE `bio_contacts`.`contact_id` = '33'
           AND `bio_contacts`.`user_id` = `bio_community_events`.`user_id`
      )

или:

SELECT `bio_community_events`.`id`, 
       `bio_community_events`.`begin_on`, 
       `bio_community_events`.`name`
  FROM `bio_community_events`
  WHERE EXISTS  
      ( SELECT *
          FROM `bio_contacts`
         WHERE ( `bio_contacts`.`user_id` = '33'
             AND `bio_contacts`.`contact_id` = `bio_community_events`.`user_id` )
           OR  ( `bio_contacts`.`contact_id` = '33'
             AND `bio_contacts`.`user_id` = `bio_community_events`.`user_id` )
      )

Если ваш план состоит в том, чтобы найти наиболее эффективный запрос, попробуйте все, что работает правильно (с помощью IN, с помощью UNION, с помощью EXISTS) - добавьте ORDER BY, который вы хотите вне курса - ипроверка их скорости и планов выполнения.

Я бы, по крайней мере, имел:

  • в таблице bio_community_events
    • индекс на user_id
    • индекс поля (полей), используемый для ORDER BY

и

  • в таблице bio_contacts, два составных индекса
    • в (contact_id, user_id) и
    • в (user_id, contact_id)

И еще один вопрос, если вы не можете запустить его менее чем за Xмиллисекунды (X решил ваш босс:)

1 голос
/ 05 июля 2011
SELECT id, begin_on, name 
FROM bio_community_events 
WHERE user_id IN ( SELECT user_id FROM bio_contacts WHERE contact_id = '33')
OR user_id IN ( SELECT contact_id FROM bio_contacts WHERE user_id = '33')
0 голосов
/ 05 июля 2011

Вам также необходимо получить идентификаторы своих друзей:

SELECT `bio_community_events`.`id`, `bio_community_events`.`begin_on`, `bio_community_events`.`name`
FROM `bio_community_events`
JOIN `bio_contacts`
    ON (`bio_contacts`.`contact_id` = `bio_community_events`.`user_id`)
WHERE `bio_contacts`.`user_id` = '33'
OR `bio_contacts`.`user_id` IN (SELECT `contact_id` FROM `contacts` WHERE `user_id` = 33)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...