只是开始学习活动记录,并且想知道如何最好地从涉及sql聚合查询的多个表中检索数据.
在以下示例中(来自医疗应用程序),我正在寻找每个患者最近的各种类型的事件(例如,上次访问,最后一次实验室测试等).从下面的SQL查询可以看到,我正在从分组查询中查找max(date)值.我使用find_by_sql来执行此操作 – 但是我想看看如何在不使用find_by_sql的情况下执行此操作.
IOW – 如何使用纯ActiveRecord方法在这里获取所需的数据.以下是我正在测试的表和类defs:
通过sql查找来检索每个类型的最新条目 – 在这里记下’max(event_date)’
strsql = "select p.lname,e.patient_id,e.event_type,max(e.event_date) as event_date from events e inner join patients p on e.patient_id = p.id group by p.lname,e.event_type"
以下是示例SQL查询结果:
lname,patient_id,event_type,latest 'Hunt',3,'Labtest','2003-05-01 00:00:00' 'Hunt','Visit','2003-03-01 00:00:00' 'Seifer',2,'2002-05-01 00:00:00' 'Seifer','2002-03-01 00:00:00' Table Relationships are: Tables ---> Patients --> Events --> visits --> labtests --> ... other patients t.string :lname t.date :dob events t.column :patient_id,:integer t.column :event_date,:datetime t.column :event_type,:string visits t.column :event_id,:integer t.column :visittype,:string labtests t.column :event_id,:integer t.column :testtype,:string t.column :testvalue,:string
类
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
解决方法
正如Pallan指出的那样:select选项不能与:include选项一起使用.但是:join选项可以.这就是你想要的.事实上,它可以采用与以下相同的参数:包含或使用您自己的sql.这里有一些粗糙的,未经测试的代码,可能需要一些小小的问题.
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.event_type")
注意我修改了一些事情.我将event_date别名重命名为max_date,所以不要混淆你所指的属性.您的:select查询中使用的属性在返回的模型中可用.例如,在这个你可以调用event.max_date.我还添加了事件ID列,因为有时候可能会遇到一些令人讨厌的错误,而没有id属性(取决于您如何使用返回的模型).
主要区别在于:include和:join是前者执行相关模型的急速加载.换句话说,它将为每个事件自动获取相关的患者对象.这需要对select语句的控制,因为它需要同时选择患者属性.与:连接患者对象未被实例化.