【发布时间】:2014-07-25 22:34:47
【问题描述】:
我正在尝试根据与listing_options 的has_many 关系查询一个表listings。列表选项有不同的类型,我想做一个可以将列表与列表选项匹配的 SQL 查询。这是 SQL 查询 atm:
SELECT "listings".* FROM "listings" INNER JOIN "listing_options" ON
"listing_options"."listing_id" = "listings"."id" WHERE ("listings".state IS NULL) AND
(listing_options.option_id IN ('1','2')) AND
(listing_options.option_id IN ('4','5','7')) LIMIT 12 OFFSET 0
假设我有两个列表,选项值分别为 (1,5) 和 (1,6)。我希望查询返回第一个列表,而不是第二个。问题是查询一次只考虑一个选项值,即选项值不能同时为 1 和 5,因此查询返回空。
ActiveRecord 生成 SQL:
Listing.joins(:listing_options).where("listing_options.option_id IN (?)", [1,2]).where("listing_options.option_id IN (?)", [4,5,7])
注意:如果查询的一部分被省略,这样构造查询会导致返回重复记录,这可能是问题的一部分。
包含包含的相同查询(也没有返回结果):
Listing.includes(:listing_options).where("listing_options.option_id IN (?)", [1,2]).references(:listing_options).where("listing_options.option_id IN (?)", [4,5,7])
类列表
has_many :listing_options
has_and_belongs_to_many :options, join_table: :listing_options
类选项
属于_to :option_type, inverse_of: :option
我尝试反转查询无济于事(尽管这样做也会更复杂,因为我需要指定 option_ids 以避免基于选项类型)。
例子:
Listing.includes(:listing_options).where("listing_options.option_id NOT IN (?)", [3,6,8]).references(:listing_options)
此查询返回列表 - 超出应有的范围。对于大量列表和最多四种列表选项(列表选项的附加查询),查询应该相当有效。出于这个原因,我只想进行一次查询,而不是重复查询结果。
编辑 - 解决方案 - 来自 @ErwinBrandstetter 的 SQL 编写为搜索范围
.where('EXISTS (SELECT 1 FROM listing_options o1 JOIN listing_options o2 USING (listing_id) WHERE o1.listing_id = id AND o1.option_id IN (?) AND o2.option_id IN (?))', [1,2], [4,5,7])
【问题讨论】:
-
您正在尝试查找具有至少一个选项
[1,2]和至少一个选项[4,5,7]的列表?所以带有选项[1,5]的东西可以,但[1,2,3]和[4,7,11]不行? -
这是relational division的特例。
标签: sql ruby-on-rails postgresql activerecord ruby-on-rails-4