根据一个字段选择不同的记录,同时保持其他字段不变

Chr*_*ell 6 activerecord ruby-on-rails

我有一张这样的桌子:

      table: searches
+------------------------------+
| id  |   address   |   date   |
+------------------------------+
| 1   | 123 foo st  | 03/01/13 |
| 2   | 123 foo st  | 03/02/13 |
| 3   | 456 foo st  | 03/02/13 |
| 4   | 567 foo st  | 03/01/13 |
| 5   | 456 foo st  | 03/01/13 |
| 6   | 567 foo st  | 03/01/13 |
+------------------------------+
Run Code Online (Sandbox Code Playgroud)

并且想要一个像这样的结果集:

+------------------------------+
| id  |   address   |   date   |
+------------------------------+
| 2   | 123 foo st  | 03/02/13 |
| 3   | 456 foo st  | 03/02/13 |
| 4   | 567 foo st  | 03/01/13 |
+------------------------------+
Run Code Online (Sandbox Code Playgroud)

但ActiveRecord似乎无法实现这一结果.这是我正在尝试的:

  • 模型具有'most_recent'范围: scope :most_recent, order('date_searched DESC')
  • Model.most_recent.uniq返回完整的set(SELECT DISTINCT "searches".* FROM "searches" ORDER BY date DESC) - 显然查询不会按我的意愿执行,但两者都不会只选择一列.我需要所有列,但只需要address结果集中唯一的行.
  • 我可以做点什么Model.select('distinct(address), date, id'),但感觉......错了.

cre*_*nig 3

你可以做一个

select max(id), address, max(date) as latest 
       from searches 
       group by address 
       order by latest desc
Run Code Online (Sandbox Code Playgroud)

根据sqlfiddle,这正是我认为你想要的。

它与您的需求输出不太一样,它似乎并不关心返回哪个ID。尽管如此,查询仍然需要指定一些内容,这里由“max”聚合函数完成。

对于这种情况,我认为您不会对 ActiveRecord 自动生成的查询方法有任何运气。因此,只需使用该 SQL 将您自己的查询方法添加到您的模型类中即可。它是完全标准的 SQL,基本上也可以在任何其他 RDBMS 上运行。

编辑:查询的一大弱点是它不一定返回实际记录。如果给定地址的最高 ID 与该地址的最高日期不相关,则生成的“记录”将与实际存储在数据库中的记录不同。取决于可能重要或不重要的用例。对于 Mysql,只需更改max(id)id即可解决该问题,但 IIRC Oracle 存在问题。