Select 行在使用 where 条件的联接 table 中没有匹配项

Select rows with no match in join table with where condition

在带有 Postgres 的 Rails 应用程序中,我有一个用户、工作和关注者加入 table。我想要 select 个未被特定用户关注的职位。但也有在联接 table.

中没有行的作业

表格:

users: 
  id: bigint (pk)

jobs:
  id: bigint (pk)

followings:
  id: bigint (pk)
  job_id: bigint (fk)
  user_id: bigint (fk)

数据:

sandbox_development=# SELECT id FROM jobs;
 id 
----
  1
  2
  3
(3 rows)
sandbox_development=# SELECT id FROM users;
 id 
----
  1
  2
sandbox_development=# 
SELECT id, user_id, job_id FROM followings;
 id | user_id | job_id 
----+---------+--------
  1 |       1 |      1
  2 |       2 |      2
(2 rows)

预期结果

# jobs
 id 
----
  2
  3
(2 rows)

我可以创建一个与此等效的连接查询吗?

sandbox_development=# 
SELECT j.id FROM jobs j 
WHERE NOT EXISTS(
  SELECT 1 FROM followings f 
  WHERE f.user_id = 1 AND f.job_id = j.id 
);

 id 
----
  2
  3
(2 rows)

这个工作是用 ActiveRecord 创建的 PITA。

到目前为止我有:

Job.joins(:followings).where(followings: { user_id: 1 })
SELECT "jobs".* FROM "jobs" 
INNER JOIN "followings" 
ON "followings"."job_id" = "jobs"."id" 
WHERE "followings"."user_id" != 1

但由于它是内部联接,因此不包括没有关注者的职位(职位 ID 3)。我还尝试了各种外连接尝试,要么给出所有行,要么不给出任何行。

我不确定我是否理解,但这有你想要的输出并使用外部连接:

SELECT j.* 
FROM jobs j LEFT JOIN followings f ON f.job_id = j.id
LEFT JOIN users u ON u.id = f.user_id AND u.id = 1 
WHERE u.id IS NULL;

在Rails 5、可以用#left_outer_joins和where not来达到效果。左联接不会 return 空行。所以,我们需要添加 nil 条件来获取行。

Rails 5 查询:

Job.left_outer_joins(:followings).where.not(followings: {user_id: 1}).or(Job.left_outer_joins(:followings).where(followings: {user_id: nil}))

备用查询:

Job.left_outer_joins(:followings).where("followings.user_id != 1 OR followings.user_id is NULL")

Postgres 查询:

SELECT "jobs".* FROM "jobs" LEFT OUTER JOIN "followings" ON "followings"."job_id" = "jobs"."id" WHERE "followings"."user_id" != 1 OR followings.user_id is NULL;