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

时间:2013-03-21 13:39:12

标签: ruby-on-rails activerecord

我有一张这样的桌子:

      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 |
+------------------------------+

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

+------------------------------+
| id  |   address   |   date   |
+------------------------------+
| 2   | 123 foo st  | 03/02/13 |
| 3   | 456 foo st  | 03/02/13 |
| 4   | 567 foo st  | 03/01/13 |
+------------------------------+

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

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

2 个答案:

答案 0 :(得分:3)

你可以做一个

select max(id), address, max(date) as latest 
       from searches 
       group by address 
       order by latest desc

根据sqlfiddle完全符合我的想法。

它与您的需求输出并不完全相同,它似乎并不关心返回哪个ID。但是,查询需要指定一些内容,这里由“max”聚合函数完成。

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

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

答案 1 :(得分:2)

显示唯一地址:

Searches.group(:address)

然后,您可以根据需要选择列:

Searches.group(:address).select('id,date')