通过关联从 has many 中查找匹配和不匹配记录的单次出现
Find single occurrence of matched and non-matched records from has many through association
我有 3 个 Postgres table
- 组
- groups_favourites
- 最爱
这 3 个 table 的结构是:
groups
--------------------------
| id | name | user_id |
--------------------------
| 1 | Group A | 100 |
| 2 | Group B | 100 |
| 3 | Group C | 100 |
| 4 | Group D | 100 |
--------------------------
favourites_groups
-------------------------------
| id | group_id | favorite_id |
-------------------------------
| 1 | 2 | 10 |
| 2 | 2 | 12 |
| 3 | 2 | 14 |
| 4 | 2 | 15 |
| 5 | 2 | 16 |
| 6 | 3 | 12 |
| 7 | 4 | 10 |
| 8 | 4 | 11 |
| 9 | 4 | 12 |
| 10 | 4 | 13 |
-------------------------------
UNIQUE INDEX ON [group_id, favorite_id]
favourites
-------------------------------
| id | product_id | user_id |
-------------------------------
| 10 | 1000 | 100 |
| 11 | 1001 | 100 |
| 12 | 1002 | 100 |
| 13 | 1003 | 100 |
| 14 | 1004 | 100 |
| 15 | 1005 | 100 |
| 16 | 1006 | 100 |
-------------------------------
我在后端的 Rails 上使用 Ruby,这 3 个 table 之间的关系是通过 [=14= 设置的]协会
我想要完成的结果是:对于给定的产品和用户,我想找到所有在 favorite_groups
table 中有条目的组 + 所有没有条目的组在 favorites_groups
table.
假设 user_id = 100
AND product_id = 1000
,结果将是:
| group_id | group_name | favorite_id | product_id |
----------------------------------------------------
| 1 | Group A | NULL | NULL |
| 2 | Group B | 10 | 1000 |
| 3 | Group C | NULL | NULL |
| 4 | Group D | 10 | 1000 |
----------------------------------------------------
另一个用例是 user_id = 100
AND product_id = 1002
,结果是:
| group_id | group_name | favorite_id | product_id |
----------------------------------------------------
| 1 | Group A | NULL | NULL |
| 2 | Group B | 12 | 1002 |
| 3 | Group C | 12 | 1002 |
| 4 | Group D | 12 | 1002 |
----------------------------------------------------
我正在使用的当前 SQL 给我 1 行 NULL
favorite_id
和 product_id
以及 1 行匹配的 favorite_id
和 product_id
这是我的 SQL:
SELECT DISTINCT ON (group_id, favorite_id, product_id) groups.id AS group_id, groups.name AS group_name, favorites.id AS favorite_id, favorites.product_id AS product_id
FROM groups
LEFT JOIN favorite_groups ON favorite_groups.group_id = groups.id
LEFT JOIN favorites ON favorites.id = favorite_groups.favorite_id AND favorites.product_id = 1002
WHERE groups.user_id = 100
由于此查询返回的结果,我必须额外工作以遍历每一行并准备我想要的结果集。
有更好的方法吗?
在此先感谢您的帮助!
您的模型有些奇怪。 groups.name
与 groups
和 favourites
中出现的 user_id
之间的关系尚不清楚。 favourites_groups
上的 unique
约束应该使 favourites
中的 user_id
变得不必要,所以我添加了一个注释掉的 join
条件。
请试试这个查询,看看它是否return是您需要的:
select g.id as group_id, g.name as group_name
from groups g
left join favourites_groups fg
on fg.group_id = g.id
left join favourites f
on f.id = fg.favorite_id
-- and f.user_id = g.user_id
where g.user_id = 100
and f.product_id = 1002
;
更新
对于那个很抱歉。这应该 return 你想要什么:
select g.id as group_id, g.name as group_name,
max(f.id) as favorite_id,
max(f.product_id) as product_id
from groups g
left join favourites_groups fg
on fg.group_id = g.id
left join favourites f
on f.id = fg.favorite_id
and f.product_id = 1000
where g.user_id = 100
group by g.id, g.name
order by g.id;
我有 3 个 Postgres table
- 组
- groups_favourites
- 最爱
这 3 个 table 的结构是:
groups
--------------------------
| id | name | user_id |
--------------------------
| 1 | Group A | 100 |
| 2 | Group B | 100 |
| 3 | Group C | 100 |
| 4 | Group D | 100 |
--------------------------
favourites_groups
-------------------------------
| id | group_id | favorite_id |
-------------------------------
| 1 | 2 | 10 |
| 2 | 2 | 12 |
| 3 | 2 | 14 |
| 4 | 2 | 15 |
| 5 | 2 | 16 |
| 6 | 3 | 12 |
| 7 | 4 | 10 |
| 8 | 4 | 11 |
| 9 | 4 | 12 |
| 10 | 4 | 13 |
-------------------------------
UNIQUE INDEX ON [group_id, favorite_id]
favourites
-------------------------------
| id | product_id | user_id |
-------------------------------
| 10 | 1000 | 100 |
| 11 | 1001 | 100 |
| 12 | 1002 | 100 |
| 13 | 1003 | 100 |
| 14 | 1004 | 100 |
| 15 | 1005 | 100 |
| 16 | 1006 | 100 |
-------------------------------
我在后端的 Rails 上使用 Ruby,这 3 个 table 之间的关系是通过 [=14= 设置的]协会
我想要完成的结果是:对于给定的产品和用户,我想找到所有在 favorite_groups
table 中有条目的组 + 所有没有条目的组在 favorites_groups
table.
假设 user_id = 100
AND product_id = 1000
,结果将是:
| group_id | group_name | favorite_id | product_id |
----------------------------------------------------
| 1 | Group A | NULL | NULL |
| 2 | Group B | 10 | 1000 |
| 3 | Group C | NULL | NULL |
| 4 | Group D | 10 | 1000 |
----------------------------------------------------
另一个用例是 user_id = 100
AND product_id = 1002
,结果是:
| group_id | group_name | favorite_id | product_id |
----------------------------------------------------
| 1 | Group A | NULL | NULL |
| 2 | Group B | 12 | 1002 |
| 3 | Group C | 12 | 1002 |
| 4 | Group D | 12 | 1002 |
----------------------------------------------------
我正在使用的当前 SQL 给我 1 行 NULL
favorite_id
和 product_id
以及 1 行匹配的 favorite_id
和 product_id
这是我的 SQL:
SELECT DISTINCT ON (group_id, favorite_id, product_id) groups.id AS group_id, groups.name AS group_name, favorites.id AS favorite_id, favorites.product_id AS product_id
FROM groups
LEFT JOIN favorite_groups ON favorite_groups.group_id = groups.id
LEFT JOIN favorites ON favorites.id = favorite_groups.favorite_id AND favorites.product_id = 1002
WHERE groups.user_id = 100
由于此查询返回的结果,我必须额外工作以遍历每一行并准备我想要的结果集。
有更好的方法吗?
在此先感谢您的帮助!
您的模型有些奇怪。 groups.name
与 groups
和 favourites
中出现的 user_id
之间的关系尚不清楚。 favourites_groups
上的 unique
约束应该使 favourites
中的 user_id
变得不必要,所以我添加了一个注释掉的 join
条件。
请试试这个查询,看看它是否return是您需要的:
select g.id as group_id, g.name as group_name
from groups g
left join favourites_groups fg
on fg.group_id = g.id
left join favourites f
on f.id = fg.favorite_id
-- and f.user_id = g.user_id
where g.user_id = 100
and f.product_id = 1002
;
更新 对于那个很抱歉。这应该 return 你想要什么:
select g.id as group_id, g.name as group_name,
max(f.id) as favorite_id,
max(f.product_id) as product_id
from groups g
left join favourites_groups fg
on fg.group_id = g.id
left join favourites f
on f.id = fg.favorite_id
and f.product_id = 1000
where g.user_id = 100
group by g.id, g.name
order by g.id;