5

所以,我在纯 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 日星期一的未定义方法“组”:日期

看起来我只是从 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 日星期一的未定义方法“组”:日期

更新:

这更接近,但我最后需要一个有子句 - 只是不确定如何将内部表和外部表绑定在一起(如在 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

有时你只需要休息一下。

4

2 回答 2

3

So, in my controller, I have this:

@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
                        )")

Then in my view, I have this:

client.insurance_providers.order('effective_on DESC').first.copay
于 2013-10-24T00:14:16.127 回答
2

我不确定为什么您undefined method 'group'在第一个查询中遇到 select 错误,在您尝试显式使用其中一个字段或调用.loador.first等​​之前,它不应该返回任何内容。

Maximum也不是要走的路,因为这将立即返回数据,并且它与 SQL "SELECT MAX(effective_on) FROM insurance_providers" 中所说的基本相同,这显然不是你想要的。

为了直接回答您的问题,总结您想要做什么,我相信您正在尝试查找effective_on日期最高的保险提供商,然后能够查看与该提供商关联的客户。如果我错了,请纠正我。

我认为这会起作用:

insuranceProvider = 
    InsuranceProvider.where("effective_on = (SELECT MAX(effective_on) FROM insurance_providers)")
                     .group(:client_id)

除此之外,你不应该需要任何其他东西。请注意我是如何在InsuranceProvider模型上调用查询的;请记住,使用 Rails,您可以使用您的has_manybelongs_to关系描述符轻松获取模型对象的关联记录。

Therefore, in order to get the associated Client model information, it is important that your InsuranceProvider class has a line that looks like belongs_to :client. This is required in this case, otherwise Rails doesn't know that this model relates to anything else. If you have that in there, then in order to get the Client information, all you simply need to do is

client = insuranceProvider.client

This will result in a second query which lazy-loads the client information for that insurance provider, and you're good to go.

EDIT

Based on the discussion in the comments, my original solution is not quite what you're looking for (and syntactically invalid for non-MySQL databases).

I answered a similar question here once that is somewhat related to this, so maybe that information could be helpful.

Basically, what I think you'll need to do is grab your list of Clients, or grab your single client object, whatever you need to do, and invoke the association with a .where clause, like so:

client = Client.first # this is for illustration so that we have a client object to work with
insurance_provider = 
    client.insurance_providers
          .where("effective_on = (SELECT MAX(effective_on) FROM insurance_providers WHERE client_id = ?", client.id)

Or, if you want to avoid having to inject the client.id manually, you can cause a dependent subquery, like so:

insurance_provider = 
    client.insurance_providers
          .joins(:client)
          .where("effective_on = (SELECT MAX(effective_on) FROM insurance_providers WHERE client_id = clients.id")
于 2013-10-23T18:09:21.557 回答