9

刚开始学习活动记录,想知道如何最好地从涉及 SQL 聚合查询的多个表中检索数据。

在以下示例中(来自医疗应用程序),我正在寻找每位患者的各种类型的最新事件(例如,上次访问、上次实验室测试等)。正如您从下面的 sql 查询中看到的那样,我正在从分组查询中查找 max(date) 值。我求助于 find_by_sql 来执行此操作 - 但是我想看看如何在不使用 find_by_sql 的情况下执行此操作。

IOW - 您将如何使用纯 ActiveRecord 方法在此处获取所需的数据。下面是我正在测试的表和类定义:

按 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, 最新
'狩猎',3,'Labtest','2003-05-01 00:00:00'
'狩猎',3,'访问','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:患者ID,:整数
      t.column :event_date, :datetime
      t.column :event_type, :string

访问
      t.column :event_id, :integer
      t.column:访问类型,:字符串

实验室测试
      t.column :event_id, :integer
      t.column :testtype, :string
      t.column:测试值,:字符串

课程

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
4

3 回答 3

14

正如 Pallan 所指出的,该:select选项不能与该:include选项一起使用。但是:joins选项可以。这就是你想要的。事实上,它可以采用与您自己的 SQL 相同的参数: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别名重命名为,max_date因此您所指的属性不会混淆。查询中使用的属性在:select返回的模型中可用。例如,在此您可以调用event.max_date. 我还添加了事件id列,因为您有时会在没有id属性的情况下遇到一些令人讨厌的错误(取决于您如何使用返回的模型)。

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

于 2009-08-03T15:03:56.957 回答
2

包含只是一个巧妙的左连接,您可以在 .find 中将其与 select 和 group_by 结合使用

于 2009-08-02T09:01:05.197 回答
0

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

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

同行

于 2009-08-02T00:26:08.377 回答