首页 > 数据库 > mysql教程 > 如何以多对多关系查询包含一组特定体育项目的商品?

如何以多对多关系查询包含一组特定体育项目的商品?

DDD
发布: 2025-01-05 07:20:44
原创
987 人浏览过

How to Query for Offers Containing a Specific Set of Sports in a Many-to-Many Relationship?

SQL 错误:“其中连接集必须包含所有值,但可能包含更多”,用于优惠和体育过滤器

在我们的数据库中,我们有三个表:优惠、 sports,以及连接表 Offers_sports。我们想要检索包含一组给定体育项目的优惠,要求必须存在所有指定的体育项目,但也可能包含其他体育项目。

例如,考虑以下优惠:

  • 轻度:瑜伽、趴板冲浪
  • 中度:瑜伽、趴板冲浪、冲浪
  • 全部:瑜伽、趴板运动、冲浪、滑翔伞、跳伞

如果我们查询包含“趴板运动”和“冲浪”的优惠,我们预计会收到“中度”和“全部”,但不会收到“轻度”。但是,我们当前的查询:

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;
登录后复制

不返回任何结果。

为了纠正这个问题,我们将查询修改为 group by优惠 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;
登录后复制

或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
登录后复制

此修改可确保我们对结果进行适当分组并应用必要的过滤标准来检索包含指定体育项目的所需优惠。

以上是如何以多对多关系查询包含一组特定体育项目的商品?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板