【问题标题】:SQL Queries using EXISTS and OR operator使用 EXISTS 和 OR 运算符的 SQL 查询
【发布时间】:2012-12-07 12:21:59
【问题描述】:

我有 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 喜欢做的是拉出属于联系人组 1 和 3 的用户或用户 1 的联系人(在 table: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)));

【问题讨论】:

  • 这应该总是返回users 表中的所有行,因为WHERE 子句中的第一个条件实际上是1=1
  • user_id 不同。我应该用 %d 替换 1 。谢谢

标签: sql subquery exists


【解决方案1】:

这就是我的做法,应该是最理想的:

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。

【讨论】:

  • 太棒了!我在上面的表格中进行了更改,并尝试删除代码中的最后一个 where 子句 WHERE c.id IS NOT NULL OR g.id IS NOT NULL... but stil query is empty 。谢谢
  • 有效!!我的代码有错误并修复它。感谢您的帮助。!
  • 这是对我有用的代码:SELECT DISTINCT a.* FROM users as a LEFT JOIN user_contacts as b ON a.id = b.contact_id AND b.user_id = %d LEFT JOIN user_contact_groups as c on c.user_id = a.id AND c.contact_group_id IN (%s) WHERE b.user_id IS NOT NULL OR c.user_id IS NOT NULL
  • @user1917451 当然,请注意%s 永远不会来自用户输入(或者恶意用户可以使用 GET 或 POST 变量更改)。使用查询参数可能会更好。
【解决方案2】:

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

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 来测试这个,但我认为它会得到正确的结果

【讨论】:

  • 感谢您的帮助,我已经更新了上面的表格。对不起,我的坏事。
  • @user1917451 我已经更新了我的答案。无需实际更改,只需检查 where 子句中的不同字段
  • 这很奇怪,我仍然收到 SQL:错误:查询为空。与其他答案相同的结果.. 嗯
  • 有效!!我的代码中有错误并修复了它。它也应该是 a.id = 1 :)...感谢您的帮助。!
  • a.id = b.user_id 所以检查哪一个并不重要——它们必须相同。加入 user_contacts 只是为了检查 user_contact 是否存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
  • 1970-01-01
  • 2021-02-18
  • 1970-01-01
  • 1970-01-01
  • 2014-10-22
相关资源
最近更新 更多