如何从一个表中获取相关表中不存在的记录?

时间:2014-05-29 12:58:16

标签: sql postgresql

我有这个users表:

users

和这个relationships表:

enter image description here

因此,每个用户都与relationships表中的另一个用户配对。

现在,我想在两列(usersrelationships)中的任意一列中获取user_id表中不在pair_id表中的列表。

我该怎么写这个查询?

首先尝试:

SELECT users.id
FROM users
LEFT OUTER JOIN relationships
ON users.id = relationships.user_id
WHERE relationships.user_id IS NULL;

输出:

enter image description here

这应该只显示2个结果:5和6.结果8不正确,因为它已经存在于relationships中。当然我知道查询不正确,我该如何解决呢?

  • 我正在使用PostgreSQL。

4 个答案:

答案 0 :(得分:4)

您需要与on语句中的两个值进行比较:

SELECT u.id
FROM users u LEFT OUTER JOIN
     relationships r
     ON u.id = r.user_id or u.id = r.pair_id
WHERE r.user_id IS NULL;

通常,or子句中的on可能效率低下。我建议用两个not exists语句替换它:

SELECT u.id
FROM users u
WHERE NOT EXISTS (SELECT 1 FROM relationships r WHERE u.id = r.user_id) AND
      NOT EXISTS (SELECT 1 FROM relationships r WHERE u.id = r.pair_id);

答案 1 :(得分:2)

我喜欢集合运算符

select id from users
  except
select user_id from relationships
  except
select pair_id from relationships

select id from users
  except
(select user_id from relationships
   union
 select pair_id from relationships
)

答案 2 :(得分:2)

这是一个特殊情况:
Select rows which are not present in other table

我认为这将是最简单和最快的:

SELECT u.id
FROM   users u
WHERE  NOT EXISTS (
   SELECT 1
   FROM   relationships r
   WHERE  u.id IN (r.user_id, r.pair_id)
   );

在Postgres中,u.id IN (r.user_id, r.pair_id)只是简称:(u.id = r.user_id OR u.id = r.pair_id) 表达式在内部以这种方式转换,可以从EXPLAIN ANALYZE观察到。

要清除评论中的推测:现代版本的Postgres将使用user_id和/或pair_id上的匹配索引进行此类查询。

答案 3 :(得分:0)

类似的东西:

select u.id
from users u
where u.id not in (select r.user_id from relationships r) 
and u.id not in (select r.pair_id from relationships r)