联系表的问题

时间:2011-07-05 15:38:26

标签: mysql sql

我有类似朋友表的东西。它被称为contacts。它有:

  • user_id是用户的ID,就像该联系人的所有者一样,
  • contact_id是与user_id;
  • 的朋友在一起的用户的ID

第二个表名为events。它有:

  • user_id是该事件的创建者的用户ID。

我需要选择朋友创建的活动。所以如果我的联系人列表中有John和Anna ......我需要显示它们的事件。

这是解决方案:

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。它给了我朋友们的活动。这就是问题......

有些情况下,我不是与朋友联系的人。反之亦然,安娜做到了。此查询将忽略该查询,并且不显示Anna的结果。

3 个答案:

答案 0 :(得分:2)

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)
    • on (user_id, contact_id)

并发布另一个问题,如果你不能让它在不到X毫秒的时间内运行(X由你的老板决定:)

答案 1 :(得分:1)

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')

答案 2 :(得分:0)

您还需要获取朋友的用户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'
OR `bio_contacts`.`user_id` IN (SELECT `contact_id` FROM `contacts` WHERE `user_id` = 33)