SQL查询使用EXISTS和OR运算符

时间:2012-12-20 02:30:25

标签: sql subquery exists

我有4张桌子

    users
    |  id  |Username|
    |   1  |  John  |
    |   2  |  Mike  |
    |   3  |  Alex  |

    user_contacts
    | user_id  |contact_id|
    |   1      |    2     |
    |   1      |    3     |
    |   2      |    3     |

    contact_groups
    | id  |  Group name  |
    |  1  |    Group 1   |  
    |  2  |    Group 2   |
    |  3  |    Group 3   |

    user_contact_groups
    | user_id  |contact_group_id|
    |   1      |    1           |
    |   1      |    2           |
    |   3      |    2           |

id喜欢做的是拉取属于Contact Group 1和3的用户或者用户1的联系人(在表:user_contacts中)。下面是代码,但它返回查询为空

SELECT DISTINCT a.* from  users as a 
WHERE EXISTS (SELECT * FROM user_contacts as b 
    WHERE b.user_id = 1) OR 
    (a.id IN (select c.user_id 
         FROM user_contact_groups as c 
            WHERE c.contact_group_id IN (1,3)));

2 个答案:

答案 0 :(得分:5)

我就是这样做的,应该是最优的:

SELECT DISTINCT u.*
FROM users u
LEFT OUTER JOIN user_contacts c ON u.id = c.contact_id 
    AND c.user_id = 1
LEFT OUTER JOIN user_contact_groups g ON u.user_id = g.user_id 
    AND g.contact_group_id IN (1,3)
WHERE c.id IS NOT NULL OR g.id IS NOT NULL

如果您想使用EXISTS,您当然可以转过来,但查询可能无法使用索引(您可以删除此查询的DISTICT):

SELECT *
FROM users u
WHERE EXISTS
(
    SELECT 1
    FROM user_contacts c 
    WHERE c.contact_id = u.id
    AND c.user_id = 1
)
OR EXISTS
(
    SELECT 1
    FROM user_contact_groups g 
    WHERE g.user_id = u.user_id
    AND g.contact_group_id IN (1,3)
)

我建议做一个EXPLAIN,看看哪个更适合你的RDBMS。

答案 1 :(得分:3)

而不是做子查询,你可以做左连接

SELECT DISTINCT a.*
FROM users as a
LEFT JOIN user_contacts as b ON a.id = b.user_id AND a.id = 1
LEFT JOIN user_contact_groups as c on c.user_id = a.id AND c.contact_group_id IN (1,3)
WHERE b.user_id IS NOT NULL OR c.user_id IS NOT NULL

我没有在我面前测试SQL,但我认为它会得到正确的结果