如何通过client_id选择max(date)和group?

时间:2013-10-23 17:09:24

标签: ruby-on-rails ruby-on-rails-4

所以,我在纯sql中按照我想要的方式工作:

select * from clients c 
    join insurance_providers p on c.id = p.client_id 
where p.effective_on = 
    (select max(effective_on) 
         from insurance_providers group by client_id having p.client_id = client_id)
and user_id = 2; #user_id =2 where 2 represents current_user.id

这是我在控制台中尝试的内容:

Client.joins(:insurance_providers)
      .select('max(insurance_providers.effective_on)')
      .group(:client_id)
      .where('user_id = 2')

它迅速在我脸上爆炸:

  

NoMethodError:2013年7月8日星期一的未定义方法“group”:日期

看起来我只是从select语句返回日期本身。我需要像"where effective_on = .select('max..."

这样的东西

任何帮助将不胜感激。

更新:我越来越接近这个:

InsuranceProvider.maximum(:effective_on, :group => 'client_id')

但我不知道如何加入客户表来获取我需要的所有信息。 在rails控制台中,这两个:

Client.joins(:insurance_providers).maximum(:effective_on, :group => 'client_id')
Client.joins(:insurance_providers.maximum(:effective_on, :group => 'client_id'))

导致此错误:

  

NoMethodError:2013年7月8日星期一的未定义方法“group”:日期

更新:

这更接近,但我最后需要一个having子句 - 只是不确定如何将内部表和外部表绑在一起(如在sql:p.client_id = client_id中):

insuranceProvider = InsuranceProvider.where("effective_on = (SELECT MAX(effective_on) FROM insurance_providers group by client_id)")
  InsuranceProvider Load (1.0ms)  SELECT "insurance_providers".* FROM "insurance_providers" WHERE (effective_on = (SELECT MAX(effective_on) FROM insurance_providers group by client_id))
PG::CardinalityViolation: ERROR:  more than one row returned by a subquery used as an expression
: SELECT "insurance_providers".* FROM "insurance_providers"  WHERE (effective_on = (SELECT MAX(effective_on) FROM insurance_providers group by client_id))
ActiveRecord::StatementInvalid: PG::CardinalityViolation: ERROR:  more than one row returned by a subquery used as an expression
: SELECT "insurance_providers".* FROM "insurance_providers"  WHERE (effective_on = (SELECT MAX(effective_on) FROM insurance_providers group by client_id))    

更新:这里有一些进展。 这似乎是我需要的,但我不知道如何将它加入到客户表中:

InsuranceProvider.where("effective_on = (SELECT MAX(effective_on) FROM insurance_providers p group by client_id having p.client_id = insurance_providers.client_id)")

这为我提供了由client_id分组的insurance_providers。我需要在client_id上加入到这个结果集。

这不起作用:

InsuranceProvider.where("effective_on = (SELECT MAX(effective_on) FROM insurance_providers p group by client_id having p.client_id = insurance_providers.client_id)").client

导致“NoMethodError”:

undefined method `client' for #<ActiveRecord::Relation::ActiveRecord_Relation_InsuranceProvider:0x007fe987725790>

更新:

这让我成为我需要的客户!

  

Client.joins(:insurance_providers).where(“insurance_providers.effective_on =(SELECT MAX(effective_on)FROM insurance_providers p group by client_id p.client_id = insurance_providers.client_id)”)

但我无法访问insurance_providers表。啊!这变得更加棘手......

更新:

client.insurance_providers.order('effective_on DESC').first.copay

有时你需要休息一下。

2 个答案:

答案 0 :(得分:2)

我不确定您为什么在第一个查询中遇到undefined method 'group'错误,在此之前它不会返回任何内容,直到您尝试显式使用其中一个字段,或者调用{ {1}}或.load

.first也不是一种方法,因为它会立即返回数据,它与SQL“SELECT MAX(effective_on)FROM insurance_providers”中的说法基本相同,这显然不是你想要的。

要直接回答您的问题,总结一下您的目标,我相信您正在尝试找到具有最高Maximum日期的保险提供商,然后能够查看与该提供商相关联的客户。如果我弄错了,请纠正我。

我认为这会奏效:

effective_on

除此之外你不需要任何其他东西。请注意我是如何在insuranceProvider = InsuranceProvider.where("effective_on = (SELECT MAX(effective_on) FROM insurance_providers)") .group(:client_id) 模型上调用查询; 请记住,使用Rails,您可以使用InsuranceProviderhas_many关系轻松获取模型对象的关联记录描述符。

因此,为了获取关联的belongs_to模型信息,您的Client类的行必须与InsuranceProvider类似。在这种情况下这是必需的,否则Rails不知道该模型与其他任何内容有关。如果您有,那么为了获得belongs_to :client信息,您只需要做的就是

Client

这将导致第二个查询延迟加载该保险提供商的客户信息,您很高兴。

修改

根据评论中的讨论,我原来的解决方案并不是你想要的(对于非MySQL数据库来说语法无效)。

我回答了一个与此有些相关的similar question here once,所以也许这些信息可能会有所帮助。

基本上,我认为你需要做的就是抓住你的client = insuranceProvider.client列表,或抓住你的单个Client对象,无论你需要做什么,并调用与{的关联{1}}子句,如下:

client

或者,如果您想避免必须手动注入client.id,可以导致依赖子查询,如下所示:

.where

答案 1 :(得分:2)

所以,在我的控制器中,我有这个:

@clients = Client.joins(:insurance_providers)
                 .where("insurance_providers.effective_on = (
                           SELECT MAX(effective_on) 
                           FROM insurance_providers p 
                           GROUP BY client_id 
                           HAVING p.client_id = insurance_providers.client_id
                        )")

然后在我看来,我有这个:

client.insurance_providers.order('effective_on DESC').first.copay