【问题标题】:How to get the most recent rows in a group如何获取组中的最新行
【发布时间】:2016-11-01 16:47:50
【问题描述】:

我有一个运行 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 行; 1、4 和 6。理想情况下,我想在单个查询中取回完整的行......但我接受我可能需要先进行一次查询以获取 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。

编辑:

基本上,我需要取回按非主键分组并按另一个字段排序的行的主键。

【问题讨论】:

  • DOH ;) 4.2.5.x ;) 我编辑

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


【解决方案1】:

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

【讨论】:

  • 我刚刚偶然发现了同样的事情......谢谢!
  • 太棒了!很高兴它对你有用。那你能接受答案吗?谢谢。
  • 我已经根据这个答案发布了我最终使用的解决方案:stackoverflow.com/a/40367494/224707
【解决方案2】:

为了澄清@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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 2016-04-07
    • 1970-01-01
    • 2015-02-25
    相关资源
    最近更新 更多