如何获取连接表中的最新条目?

时间:2012-02-16 21:43:31

标签: sql ruby-on-rails

我正在使用Rails 3.1,MySQL并使用3个类:Computer,LifecycleStatus& LifecycleEntry

我希望跟踪计算机LifecycleStatus的历史记录,以便LifecycleEntry中的列为:computer_id:integer,lifecycle_status_id:integer和changed_at:datetime。计算机可以在LifecycleStatus中有多个条目。

我设置了以下关联:

Computer
  has_many :lifecycle_entries, :order => "changed_at DESC"
  has_many :lifecycle_statuses, :through => :lifecycle_entries

LifecycleEntry
  belongs_to :computer
  belongs_to :lifecycle_status

LifecycleStatus
  has_many :lifecycle_entries

对于特定的LifecycleStatus,我想看看哪些计算机当前(它们最近的lifecycle_entries记录)已分配给该状态。

我已设法创建正确的SQL来检索此信息,但我不确定如何将其转换为Rails关联:

SELECT id, le.computer_id, lifecycle_status_id
FROM lifecycle_entries AS le
INNER JOIN (
    SELECT lemax.computer_id, MAX(changed_at) AS latest
    FROM lifecycle_entries AS lemax
    GROUP BY lemax.computer_id
) maxdates
ON le.changed_at = maxdates.latest
AND le.computer_id = maxdates.computer_id
WHERE lifecycle_status_id = 6

1 个答案:

答案 0 :(得分:1)

如果您将'active'状态非规范化到LifecycleEntry本身,每次创建新条目时更新它,这似乎会更简单。每次阅读时,这都可以为您节省GROUP BY / MAX查询。

如果你有状态列,它就像LifecycleEntry.active.where(:lifecycle_status_id => 6).computers一样简单,其中active是LifecycleEntry上的一个范围。

请执行以下操作:

  • active布尔字段添加到LifecycleEntry
  • LifecycleEntry模型添加回调以设置有效条目

这是回调:

after_save :set_active

private

def set_active
  last_active_entry = self.computer.active_lifecycle_entry

  if last_active_entry.nil?
     update_attributes(:active => true)
  elsif changed_at > last_active_entry.changed_at
     last_active_entry.update_attributes(:active => false)
     update_attributes(:active => true)
  end
end

重要的是要注意,正在创建的LifecycleEntry可能位于当前活动的LifecycleEntry之前,因此只有在changed_at之后才能将新的LifecycleEntry设置为活动状态。此外,对于创建的第一个LifecycleEntry,始终设置为active。