Active Record在一个查询中选择多个

时间:2017-06-16 13:02:40

标签: rails-activerecord

我要写什么ActiveRecord来实现这一目标:

SELECT COUNT(*), SUM(`users`.`sign_in_count`), MAX(`users`.`sign_in_count`) FROM `users` WHERE (`users`.`some_field` = 'some_condition')

我怀疑语法模糊:

User.where(some_field: some_condition).count.and.sum(:sign_in_count).and.maximum(:sign_in_count)

目前有这个:

:001:0> User.where(some_field: some_condition).count
  (1ms) SELECT COUNT(*) FROM `users` WHERE (`users`.`some_field` = 'some_condition')
=> 10
:002:0> User.where(some_field: some_condition).sum(:sign_in_count)
  (1ms) SELECT SUM(`users`.`sign_in_count`) FROM `users` WHERE (`users`.`some_field` = 'some_condition')
=> 100
:003:0> User.where(some_field: some_condition).maximum(:sign_in_count)
  (1ms) SELECT MAX(`users`.`sign_in_count`) FROM `users` WHERE (`users`.`some_field` = 'some_condition')
=> 50

ActiveRecord是否能够在一个查询中进行多项选择?我的真实世界用例有点重,并且具有多个条件,因此在过滤后值得抓取所有结果。我想我可以做:

:004:0> all_things = User.select(:sign_in_count).where(some_field: some_condition)

但每当你打电话时,它仍然会打电话:

:005:0> all_things.count
  (1ms) SELECT COUNT(*) FROM `users` WHERE (`users`.`some_field` = 'some_condition')
=> 10
:006:0> all_things.sum(:sign_in_count)
  (1ms) SELECT SUM(`users`.`sign_in_count`) FROM `users` WHERE (`users`.`some_field` = 'some_condition')
=> 100
:007:0> all_things.maximum(:sign_in_count)
  (1ms) SELECT MAX(`users`.`sign_in_count`) FROM `users` WHERE (`users`.`some_field` = 'some_condition')
=> 50

所以我可以.to_a并被迫使用不那么优雅的方法

:008:0> all_things = User.select(:sign_in_count).where(some_field: some_condition).to_a
  User Load (0.9ms)  SELECT `users`.`sign_in_count` FROM `users` WHERE (`users`.`some_field` = 'some_condition')
=> [#<User id: nil, sign_in_count: 0>, ... many elements
:009:0> all_things.count
=> 10
:010:0> all_things.inject(0){|r,e| r+e.sign_in_count}
=> 100
:011:0> all_things.inject(0){|r,e| [r,e.sign_in_count].max}
=> 50

必须采用一种漂亮的方式......这并不会迫使我将数百万行存入内存而不是一些结果,或者这样做:

:012:0> count, sum, max = ActiveRecord::Base.connection.execute("SELECT COUNT(*), SUM(`users`.`sign_in_count`), MAX(`users`.`sign_in_count`) FROM `users` WHERE (`users`.`some_field` = 'some_condition')").to_a.first

1 个答案:

答案 0 :(得分:1)

使用select

stats = User.select("count(*) as num_users", "sum(sign_in_count) as total_sign_ins", "max(sign_in_count) as max_sign_ins")
            .where(age: 18).first

然后您可以这样访问:

stats.num_users
stats.total_sign_ins
stats.max_sign_ins