如何使Active Record连接返回唯一对象?

Zac*_* Xu 38 activerecord ruby-on-rails

我有一个简单的查询需求:查找自2013年1月1日起订购的用户列表.

在SQL中,这是一个非常简单的查询.

但我正在使用Rails和Active Record.

所以我写道: User.joins(:orders).where("orders.created_at >= '2013-01-01 00:00:00'")

在我们的数据库中,我们自2013年1月1日起有75个用户发出了100个订单.(显然有些用户发了多个订单.)

但是,上面的表达式返回100个用户.(必须有重复.)

我试过了 User.joins(:orders).where("orders.created_at >= '2013-01-01 00:00:00'").uniq

这也行不通.

如何获得自2013年1月1日起订购的75位用户?

amc*_*lan 48

@dbjohn有正确的想法,但我认为你想避免创建额外的对象.这是他的解决方案的一个轻微变体,让数据库为您执行任务:

date = "2013-01-01 00:00:00"
User.joins(:orders).where("orders.created_at >= ?", date).distinct
Run Code Online (Sandbox Code Playgroud)

请注意,您可以重新排列方法的顺序以适合您认为最具语义的任何方式,ActiveRecord将为您编写相同的SQL.

  • 只是想为迟到的人指出,返回的 sql 查询是“select unique on users.* from users inside join orders on order.user_id = users.id ...”重要的一点是,它是不同的在整个记录上,这可能不是您想要的。根据您的具体用例: ``` User.eager_loads(:orders)... ``` 生成“select users.id as x, ...orders.id as y,... from users leftouter将订单加入 order.user_id = users.id ...” 这样做的好处是返回的用户具有订单关联_loaded_ (2认同)

kon*_*yak 9

User.joins(:orders).
    where("orders.created_at >= '2013-01-01 00:00:00'").
    group('users.id')
Run Code Online (Sandbox Code Playgroud)

group 方法将链接到查询并为您提供唯一记录的列表.