Rails的Active Record可以处理SQL聚合查询吗?

刚开始学习活动记录,我想知道如何最好地从涉及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.patient_id, e.event_type" 

这是示例sql查询结果:

 lname,patient_id,event_type,latest
 'Hunt',3,'Labtest','2003-05-01 00:00:00'
 'Hunt',3,'Visit','2003-03-01 00:00:00'
 'Seifer',2,'Labtest','2002-05-01 00:00:00'
 'Seifer',2,'访问','2002-03-01 00:00:00'

表关系是:
表--->患者 - >事件
                                - >访问
                                - >实验室
                                - > ......其他
耐心
       t.string:lname
       t.date:dob

事件
       t.column:patient_id,:整数
       t.column:event_date,:datetime
       t.column:event_type,:string

访问 
       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 :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选项一起使用。 但是:joins选项可以。 这就是你想要的。 实际上,它可以采用相同的参数:include或使用您自己的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.patient_id, events.event_type") 

注意我稍微修改了一下。 我将event_date别名重命名为event_date ,因此不会混淆您所指的属性。 您的:select查询中使用的属性在返回的模型中可用。 例如,您可以在event.max_date调用event.max_date 。 我还添加了事件id列,因为有时你可以在没有id属性的情况下得到一些讨厌的错误(取决于你如何使用返回的模型)。

以下:include:joins之间的主要区别在于前者执行关联模型的急切加载。 换句话说,它将自动为每个事件获取相关的患者对象。 这需要控制select语句,因为它需要同时选择患者属性。 用:joins患者对象未实例化。

include只是一个聪明的左连接,你可以在.find中与select和group_by结合使用

在当前版本的AR(2.3)中,我认为您唯一的选择是使用find_by_sql。 为什么? 您的自定义SELECT属性。 ActiveRecord允许:select和:包含查找调用的参数。 不幸的是它们不能一起使用。 如果同时指定:select将被忽略。 在您的示例中,您需要select来限制列并获得MAX函数。

我听说有一个补丁/黑客让他们一起工作,但我不知道它在哪里。

窥视