2010-04-30 46 views
1

比如这个查询:Mysql问题:有没有像IN ALL查询?

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属性,这可能与MySQL?奖金的问题,有没有一种快速的方式来使用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 
    }} 

回答

3

Assiuming即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 
+0

谢谢,这个作品!请在我的帖子下面阅读我在Rails中使用的named_scope。 – jaycode 2010-05-09 14:58:47

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) 

此代码尚未经过测试。

+0

代码太复杂了......并且它返回错误:Mysql :: Error:未知列'(:length =(从variant_attributes中选择count(*)... 如何修复? 谢谢你试图帮忙 – jaycode 2010-05-09 13:35:27

+0

哎呀,我在结果[:条件] =的时候有了错误的括号......我把{}括号放进去了,但那是错误的。我已经更正了使用[]括号的答案。 关于并发症...您想要一个本机不支持的功能。为了使它易于使用需要一些工作。 – Tilendor 2010-05-10 16:35:58

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) 
0

谢谢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 
    }}