2017-06-16 136 views
0

什麼的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

使用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