2010-04-30 43 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 
    }}