9
votes

Les rails peuvent-ils intervenir les requêtes d'agrégats SQL?

Je viens de commencer à apprendre l'enregistrement actif et je me demande comment récupérer la meilleure récupération de données à partir de plusieurs tables où une requête agrégée SQL est impliquée.

Dans l'exemple suivant (d'une application médicale), je recherche les événements les plus récents de divers types pour chaque patient (par exemple, la dernière visite, Dernière Labtest, etc.). Comme vous pouvez le constater dans la requête SQL ci-dessous, je recherche la valeur max (date) d'une requête groupée. J'ai eu recours à la Find_by_sql pour le faire - Cependant, j'aimerais voir comment faire cela sans utiliser Find_By_SQL. P>

Iow - Comment obtiendriez-vous les données requises ici à l'aide d'une approche Pure Activerecord. Vous trouverez ci-dessous la table et la classe defs que je passe avec: p>

Recherchez par SQL pour récupérer les entrées les plus récentes pour chaque type - Notez le 'Max (Event_Date)' ici P>

class Patient < ActiveRecord::Base
  has_many :events
  has_many :visits, :through =>:events
  has_many :labtests, :through => :events
end

class Event < ActiveRecord::Base
  has_many :visits
  has_many :labtests
  belongs_to :patient
end

class Visit < ActiveRecord::Base
  belongs_to :event
end

class Labtest < ActiveRecord::Base
    belongs_to :event
end


0 commentaires

3 Réponses :


0
votes

Dans la version actuelle d'AR (2.3), je pense que votre seule option est d'utiliser Find_By_SQL. Pourquoi? Vos attributs de sélection personnalisés. Activerecord permet: Sélectionner et: inclure des arguments à l'appel de recherche. Malheureusement, ils ne peuvent pas être utilisés ensemble. Si vous spécifiez les deux: Sélectionner sera ignoré. Dans votre exemple, vous avez besoin de sélectionner pour limiter vos colonnes et obtenir votre fonction max.

J'ai entendu dire qu'il y a un patch / hack pour les amener à travailler ensemble, mais je ne suis pas sûr où il se trouve.

peer


1 commentaires

Existe-t-il un moyen d'utiliser un explicitement: rejoindre au lieu de se déplacer pour contourner cette limitation? Serait-ce une option ici?



2
votes

Inclure est juste une jointure gauche intelligente, vous pouvez utiliser cela en conjonction avec Sélectionner et grouper dans votre .Find


0 commentaires

14
votes

Comme Pallan a signalé, le : Sélectionnez l'option code> ne peut pas être utilisé avec l'option : Inclure l'option code>. Cependant, le : joint une option code> peut. Et c'est ce que vous voulez ici. En fait, il peut prendre les mêmes arguments que : inclure code> ou utiliser votre propre SQL. Voici un code rugueux et non testé, peut avoir besoin d'un triple mineur.

Event.all(:select => "events.id, patients.lname, events.patient_id, events.event_type, max(events.event_date) as max_date", :joins => :patient, :group => "patients.lname, events.patient_id, events.event_type")


2 commentaires

Suivi rapide ici de OP. Avec 1 mineur Tweak: Joinages (VS: Joindre) Le code de Ryan fonctionne et remplace la requête Find_By_SQL dans mon message d'origine. Très cool. Cependant, en passant, je vais simplement noter que (AFaik) et non toutes les requêtes SQL peuvent être implémentées via des appels ORM (par exemple, une requête syndicale qui combine des valeurs min et max d'une table). Je suppose que cela nécessitera 2 appels distincts via l'ORM, tandis qu'une Find_By_SQL peut le faire dans 1 appelez par ex. Find_By_SQL ("Sélectionnez Min (T.Event_Date) à partir du tableau T Union Select max (t.event_date) du tableau T")


Mise à jour du message original à utiliser: jointures. Vous êtes correct cependant, toutes les questions ne peuvent pas être faites avec l'ormes, et ce n'est pas l'objectif de l'enregistrement actif. Il a été conçu à dessein pour adapter la majorité des besoins bien et laisser le reste possible avec Find_By_SQL. Il n'essaie pas de tout faire, alors n'hésitez pas à utiliser Find_By_SQL s'il convient mieux au travail.