2016-05-26 1 views
1

J'ai une table de jointure lab_tests qui stocke une liste de tests qu'un laboratoire particulier a avec le schéma lab_id et test_id.Rejoindre la requête d'enregistrement actif de table

Je veux obtenir une liste des laboratoires qui ont tous les tests qui sont passés dans les paramètres.

J'ai actuellement la portée suivante -

scope :test_filter, lambda {|test_id| 
    return nil if test_id.blank? 
    where(:test_id => test_id) 
} 

Mais cela me donne une liste des laboratoires avec au moins un test. Comment puis-je obtenir une liste de laboratoires contenant tous les tests dans les paramètres donnés?

Répondre

1

Vous pouvez utiliser l'astuce en utilisant GROUP BY et HAVING. Si vous filtrez votre table d'association pour tous les test_id désirés et groupez-la par lab_id, alors si le nombre d'enregistrements groupés est le même que le nombre de tests, vous êtes certain que le laboratoire inclut tous ces tests (il peut inclure d'autres tests cependant mais je suppose que cela ne vous dérange pas).

, essayez quelque chose comme ceci:

# Lab model: 
scope :with_tests, -> (test_ids) { 
    return Lab.none if test_ids.blank? 

    joins(:lab_tests). 
    where(lab_tests: { test_id: test_ids }). 
    group(:lab_id). 
    having("count(*) = ?", test_ids.count) 
} 

Notes:

  • La portée renvoie une none scope en cas de vide test_ids. Il s'agit d'une meilleure approche, puis renvoyer nil parce que none est une portée en chaîne normale qui peut être utilisée de la même manière que d'autres étendues (le chaînage nil lèverait une exception).
  • Vous n'avez pas spécifié où réside votre étendue, donc j'ai pensé que le modèle de laboratoire pourrait être un bon endroit - de cette façon, la portée renvoie les Labs avec au moins les tests donnés.
  • L'étendue se joint à la table d'association et ne filtre que les enregistrements portant le code test_ids. test_ids devrait être un tableau d'ID de test voulu dans le laboratoire. La condition sera exécutée en tant que clause IN dans la condition WHERE du SQL.
  • Ensuite, il utilise le tour de regroupement - il regroupe par lab_id et renvoie uniquement les enregistrements qui ont le même nombre de tests dans le groupe que le nombre de tests d'entrée. C'est à dire. il retourne seulement les laboratoires qui ont au moins tous les tests donnés.
+0

travaillé parfaitement! Merci! –