gpt4 book ai didi

SQL 其中连接集必须包含所有值但可能包含更多

转载 作者:行者123 更新时间:2023-11-29 12:43:48 25 4
gpt4 key购买 nike

我有三个表 offerssports 和连接表 offers_sports

class Offer < ActiveRecord::Base
has_and_belongs_to_many :sports
end

class Sport < ActiveRecord::Base
has_and_belongs_to_many :offers
end

我想选择包含一组给定运动名称的优惠。它们必须包含所有运动,但可以包含更多。

假设我有这三个优惠:

light:
- "Yoga"
- "Bodyboarding"
medium:
- "Yoga"
- "Bodyboarding"
- "Surfing"
all:
- "Yoga"
- "Bodyboarding"
- "Surfing"
- "Parasailing"
- "Skydiving"

给定数组 ["Bodyboarding", "Surfing"] 我想得到 mediumall 但不是 light

我尝试了类似 this answer 的方法但我在结果中得到零行:

Offer.joins(:sports)
.where(sports: { name: ["Bodyboarding", "Surfing"] })
.group("sports.name")
.having("COUNT(distinct sports.name) = 2")

转换为 SQL:

SELECT "offers".* 
FROM "offers"
INNER JOIN "offers_sports" ON "offers_sports"."offer_id" = "offers"."id"
INNER JOIN "sports" ON "sports"."id" = "offers_sports"."sport_id"
WHERE "sports"."name" IN ('Bodyboarding', 'Surfing')
GROUP BY sports.name
HAVING COUNT(distinct sports.name) = 2;

ActiveRecord 答案会很好,但我会满足于只使用 SQL,最好是与 Postgres 兼容。

数据:

offers
======================
id | name
----------------------
1 | light
2 | medium
3 | all
4 | extreme

sports
======================
id | name
----------------------
1 | "Yoga"
2 | "Bodyboarding"
3 | "Surfing"
4 | "Parasailing"
5 | "Skydiving"

offers_sports
======================
offer_id | sport_id
----------------------
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2
3 | 3
3 | 4
3 | 5
4 | 3
4 | 4
4 | 5

最佳答案

offer.id 分组,而不是按 sports.name(或 sports.id)分组:

SELECT o.*
FROM sports s
JOIN offers_sports os ON os.sport_id = s.id
JOIN offers o ON os.offer_id = o.id
WHERE s.name IN ('Bodyboarding', 'Surfing')
GROUP BY o.id -- !!
HAVING count(*) = 2;

假设典型的实现:

  • offer.idsports.id 定义为主键。
  • sports.name 被定义为唯一的。
  • (sport_id, offer_id)offers_sports 中定义为唯一(或 PK)。

计数中不需要 DISTINCT。而且 count(*) 甚至更便宜一些。

包含一系列可能技术的相关答案:


由@max(OP)添加 - 这是将上述查询整合到 ActiveRecord 中:

class Offer < ActiveRecord::Base
has_and_belongs_to_many :sports
def self.includes_sports(*sport_names)
joins(:sports)
.where(sports: { name: sport_names })
.group('offers.id')
.having("count(*) = ?", sport_names.size)
end
end

关于SQL 其中连接集必须包含所有值但可能包含更多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36131803/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com