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;
在带有 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;