例如此查询:
SELECT `variants`.*
FROM `variants` INNER JOIN `variant_attributes`
ON variant_attributes.variant_id = variants.id
WHERE (variant_attributes.id IN ('2','5'))
变体has_many variant_attributes
我真正想要做的是找到哪个变体具有ID = 2和5的BOTH变体属性。这可能与MySQL有关吗? Bonus Question,有没有一种快速的方法可以使用Ruby on Rails,也许使用SearchLogic?
溶液
感谢Quassnoi提供的查询,这完美无缺。
要在Rails上使用,我使用下面的named_scope,我认为这对于初学者来说更容易理解。
基本上,named_scope将返回{:from => x,:conditions => y}和上面的行用于设置y变量。
named_scope :with_variant_attribute_values, lambda { |values|
conditions = ["(
SELECT COUNT(*)
FROM `variant_attributes`
WHERE variant_attributes.variant_id = variants.id
AND variant_attributes.value IN (#{values.collect { |value| "?" }.join ", "})
) = ?
"]
conditions = conditions + values + [values.length]
{
:from => 'variants',
:conditions => conditions
}}
答案 0 :(得分:3)
确认variant_attributes (variant_id, id)
是唯一的:
SELECT `variants`.*
FROM `variants`
WHERE (
SELECT COUNT(*)
FROM `variant_attributes`
WHERE variant_attributes.variant_id = variants.id
AND variant_attributes.id IN ('2','5')
) = 2
答案 1 :(得分:1)
Quassnoi发布了你想做的mysql查询。以下是Variant
模型的方法,它将执行等效操作。我正在做两种方法,一种方法是variant_attributes (variant_id, id)
是一种独特的组合,一种方法如果它们不是
独特性:
class Variant < ActiveRecord::Base
has_many :variant_attributes
named_scope :with_variant_attributes, lamda { |*ids|
ids = ids.flatten
if(ids.length>0)
result = {:include => :variant_attributes}
sql_params = {:length => ids.length,:ids => ids}
result[:conditions] = ["(:length = (select count(*) from variant_attributes
where id in (:ids))",sql_params]
result
else
nil
end
}
end
非独特
class Variant < ActiveRecord::Base
has_many :variant_attributes
named_scope :with_variant_attributes, lamda { |*ids|
ids = ids.flatten
if(ids.length>0)
result = {:include => :variant_attributes}
conditions = []
sql_params = {}
ids.each_with_index do |id,i|
conditions << "( 1 = Select Count(*) from variant_attributes where id = :id#{i})"
sql_params["id#{i}"] = id
end
result[:conditions] = [ '(' + conditions.join(' AND ') + ')', sql_params]
result
else
nil
end
}
end
可以通过以下方式使用:
# Returns all Variants with variant_attributes 1, 2, & 3
vars = Variant.with_variant_attributes(1,2,3)
# Returns Variant 5 if it has attributes 3 & 5, or null if it doesn't
vars = Variant.with_variant_attributes(3,5).find_by_id(5)
#Returns Variants between 1 and 20 if that have an attribute of 2
vars = Variant.with_variant_attributes(2).find(:conditions => "id between 1 and 20")
#can accept a variable array of ids
my_ids = [3,5]
vars = Variant.with_variant_attributes(my_ids)
此代码尚未经过测试。
答案 2 :(得分:0)
我会为此创建一个named_scope:
class Variant < ActiveRecord::Base
has_many :variant_attributes
named_scope :with_variant_attributes, lambda { |*ids| {
:joins => :variant_attributes,
:conditions => {:variant_attributes=>{:id=>ids}},
:group => "variants.id",
:having => "count(variants.id) = #{ids.size}"
}
}
end
现在您可以按如下方式使用命名范围:
Variant.with_variant_attributes(1,2)
Variant.with_variant_attributes(1,2,3,4)
答案 3 :(得分:0)
感谢Quassnoi提供的查询,这完美无缺。
要在Rails上使用,我使用下面的named_scope,我认为这对于初学者来说更容易理解。
基本上,named_scope将返回{:from =&gt; x,:conditions =&gt; y}和上面的行用于设置y变量。
named_scope :with_variant_attribute_values, lambda { |values|
conditions = ["(
SELECT COUNT(*)
FROM `variant_attributes`
WHERE variant_attributes.variant_id = variants.id
AND variant_attributes.value IN (#{values.collect { |value| "?" }.join ", "})
) = ?
"]
conditions = conditions + values + [values.length]
{
:from => 'variants',
:conditions => conditions
}}