我如何在Ruby on Rails中构建仅在has_many关系的最大值上联接并在该关系上包括选择过滤器的查询?

问题描述 投票:2回答:7

我正在努力让Ruby on Rails正确执行此查询...总之:通过该关系中的最新记录加入has_many关系,但only可以然后应用过滤器/选择该关系。

这是捕捉我奋斗的一个超级简单的变体:


假设我有一个Employees表和一个Employments表。一个employee has_many employmentsemploymentstatus:active:inactive

class Employee < ActiveRecord::Base
  has_many :employments
end

class Employment < ActiveRecord::Base
  belongs_to :employee
end

[为了简单起见,假设有一个employee:丹和他有两个employments:一个旧的(由created_at表示)为:inactive,一个新的为:active。] >

dan = Employee.create(name: 'Dan')
Employment.create(employee: dan, created_at: 2.years.ago, status: :inactive)
Employment.create(employee: dan, created_at: 3.months.ago, status: :active)

因此,实际上,您可以说:“丹工作了两次,目前正在积极工作。”

我想要的是Rails查询,它说:“找到不活跃的员工”。这应该返回一个空集,因为Dan的latest

employment:active。所以我不能只做:Employee.joins(:employments).where(employments: { status: :inactive }),因为它会与old employment匹配并因此返回Dan employee记录。

[我需要说一句:“仅根据最新

雇用记录来查找处于非活动状态的员工”。

但是我不知道如何在Rails中做到这一点。

[我觉得我想念一些东西...应该很简单...但是我无法弄清楚。

谢谢!

我正在努力让Ruby on Rails正确执行此查询……简而言之:加入has_many关系,但只能通过该关系中的最新记录,然后可以对该条件应用过滤器/选择。 。

ruby-on-rails ruby postgresql greatest-n-per-group
7个回答
1
投票

我能想到的最简单的解决方案(基于代码的复杂性)是首先获取具有其最大值的工作ID,然后使用结果组合一个新查询。


3
投票

在具有大量行的应用程序中,我为完全相同的问题付出了很多努力,在尝试了各种新颖的解决方案(如横向联接和子查询)之后,性能最好,到目前为止最简单的解决方案是在表中添加外键指向最新行,并使用关联回调(或db trigger)设置外键。


1
投票

[摆弄了一会儿(并尝试了所有大家提出的所有建议,再加上其他建议),我想到了这个。它有效,但可能不是最优雅的。


0
投票

+ 1为@max的答案。


0
投票

由于标题包括ARel。以下示例适用于您的示例:


0
投票

我认为您可以先获取这些最大日期,以确保不会获取旧记录,然后仅过滤所需的状态。这是执行第一部分的示例]


0
投票

一种替代方法是使用LATERAL JOIN,这是Postgres 9.3+的特定功能,可以描述为类似SQL foreach循环的事物。

© www.soinside.com 2019 - 2024. All rights reserved.