如何获取组中的最新行

时间:2016-11-01 16:47:51

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

我有一个运行PostGres的Rails 4.2.5.x项目。我有一个与此类似的结构表:

id, contact_id, date,     domain, f1, f2, f3, etc
1,  ABC,        01-01-16, abc.com, 1,  2,  3, ...
2,  ABC,        01-01-15, abc.com, 1,  2,  3, ...
3,  ABC,        01-01-14, abc.com, 1,  2,  3, ...
4,  DEF,        01-01-15, abc.com, 1,  2,  3, ...
5,  DEF,        01-01-14, abc.com, 1,  2,  3, ...
6,  GHI,        01-11-16, abc.com, 1,  2,  3, ...
7,  GHI,        01-01-16, abc.com, 1,  2,  3, ...
8,  GHI,        01-01-15, abc.com, 1,  2,  3, ...
9,  GHI,        01-01-14, abc.com, 1,  2,  3, ...
...
...
99, ZZZ,        01-01-16, xyz.com, 1,  2,  3, ...

我需要查询才能找到:

  • date
  • 的最新行
  • 按域
  • 过滤
  • 表示不同的contact_id(按?分组)
  • 行限制结果。在这个例子中,我没有添加这个复杂功能,但需要将其考虑在内。如果有50个不同的联系人,我只对按日期排在前3位感兴趣。
  • ID是主键。
  • 其他列上有索引
  • fX列表示模型中需要的其他数据(例如联系电子邮件)。

在MySQL中,这将是一个简单的SELECT * FROM table WHERE domain='abc.com' GROUP BY contact_id ORDER BY date DESC,但是,PostGres在这种情况下抱怨:

ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "table.id" must appear in the GROUP BY clause or be used in an aggregate function

我希望能回来3排;在理想情况下,我想在单个查询中获取完整行...但我接受我可能需要先执行一个查询以获取ID,然后将另一个查询到find我想要的物品。

这是我最接近的:

ExampleContacts
  .select(:contact_id, 'max(date) AS max_date')
  .where(domain: 'abc.com')
  .group(:contact_id)
  .order('max_date desc')
  .limit(3)

然而......这会返回contact_id,而不是id。我无法添加该行的ID。

编辑:

基本上,我需要获取主键,该行在非主键上分组并按其他字段排序。

2 个答案:

答案 0 :(得分:1)

如果您想要行,则不需要分组。它只是Contact.select('DISTINCT ON (contact_id)').where(domain: 'abc.com').order(date: :desc).limit(3)

答案 1 :(得分:0)

为了澄清@ murad-yusufov接受的答案,我最终做到了这一点:

subquery = ExampleContacts.select('DISTINCT ON (contact_id) *')
                          .where(domain: 'abc.com')
                          .order(contact_id)
                          .order(date: :desc)

ExampleContacts.from("(#{subquery.to_sql}) example_contacts")
               .order(date: :desc)