2010-04-30 4 views
1

Par exemple cette requête:Question Mysql: Y a-t-il quelque chose comme IN ALL query?

SELECT `variants`.* 
    FROM `variants` INNER JOIN `variant_attributes` 
    ON variant_attributes.variant_id = variants.id 
WHERE (variant_attributes.id IN ('2','5')) 

Et has_many variante variant_attributes

Ce que je veux vraiment faire est de trouver quelle variante a deux attributs variante avec ID = 2 et 5. Est-ce possible avec MySQL? Question bonus, existe-t-il un moyen rapide de faire cela avec Ruby on Rails, peut-être avec SearchLogic?

solution

Merci Quassnoi pour la requête que vous avez fourni, qui a parfaitement fonctionné.

Pour utiliser sur Rails, j'ai utilisé le named_scope ci-dessous, je pense que c'est plus simple à comprendre pour les débutants. Fondamentalement named_scope renverrait {: from => x,: conditions => y} et les lignes ci-dessus ont été utilisées pour configurer la variable 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 
    }} 

Répondre

3

Assiuming que variant_attributes (variant_id, id) est unique:

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

Merci, ça fonctionne! Veuillez lire mon message ci-dessous pour named_scope que j'utilise dans Rails. – jaycode

1

Quassnoi a posté la requête MySQL qui fait ce que vous voulez. Voici une méthode pour le modèle Variant qui fera l'équivalent. Je fais deux approches, l'une si variant_attributes (variant_id, id) sont une combinaison unique, et une si elles ne sont pas

unique:

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 

non unique

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 

qui peut être utilisé dans la façons suivantes:

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

Ce code n'a pas été testé.

+0

le code est trop compliqué ... et il renvoie l'erreur: Mysql :: Erreur: Unknown column « (: longueur = (select count (*) de variant_attributes comment corriger...? Merci d'avoir essayé d'aider si – jaycode

+0

Oups, j'avais les mauvaises parenthèses sur les résultats [: conditions] = ... J'avais mis {} entre parenthèses, mais c'était faux. J'ai corrigé la réponse pour utiliser les crochets []. A propos de la complication ... Vous voulez une fonctionnalité qui n'est pas prise en charge de manière native. Pour le rendre facile à utiliser prend du travail. – Tilendor

0

Je voudrais créer un named_scope pour cela:

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 

Maintenant, vous pouvez utiliser le champ nommé comme suit:

Variant.with_variant_attributes(1,2) 
Variant.with_variant_attributes(1,2,3,4) 
0

Merci Quassnoi pour la requête que vous avez fourni, qui a parfaitement fonctionné.

Pour utiliser sur Rails, j'ai utilisé le named_scope ci-dessous, je pense que c'est plus simple à comprendre pour les débutants. Fondamentalement named_scope renverrait {: from => x,: conditions => y} et les lignes ci-dessus ont été utilisées pour configurer la variable 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 
    }} 
Questions connexes