2016-11-17 90 views
0

我想用ActiveRecord獲取日期範圍內的第一個和最後一個項目。我可以在ActiveRecord日期範圍查詢中獲取第一個和最後一個項目的最快方法?

BalanceLedger.where(created_at: Time.now-7.days..Time.now).order(:created_at).first

BalanceLedger.where(created_at: Time.now-7.days..Time.now).order(:created_at).last

進入這個每週範圍內第一個和最後一個,但是這似乎是它只是返回大量的與時,我只是在尋找每個查詢2個條目。

在這個範圍內獲得第一個和最後一個是最有效的?

+2

所寫的查詢每個都會返回一條記錄('.order(:created_at).first'將會產生一個類似'... ORDER BY created_at LIMIT 1'的查詢,同樣對於' .last'),所以我不確定你的意思,「它只會返回很多與每個查詢。」 –

+0

@Jordan我在Rails 3.2中,如果它很重要。我以爲這個查詢會返回大量的ActiveRecord對象,然後我只是第一次和最後一次採摘。 – slindsey3000

+1

不,'Model.where(...)。order(...)'給你一個關係,但不接觸數據庫,在關係上調用'first'或'last'調整查詢以包含LIMIT子句(並顛倒'last'情況下的順序),然​​後將單行查詢發送到數據庫。 –

回答

1

您不必運行兩個查詢。您可以運行一個查詢,然後在其上調用 firstlast

您可以通過以下方式改進代碼,但無論如何這兩個查詢都會運行。感謝@muistooshort@jordan在評論中指出這件事。

balance_ledgers = BalanceLedger.where(created_at: Time.now-7.days..Time.now).order(:created_at) 
first_one = balance_ledgers.first 
last_one = balance_ledgers.last 

編輯:

實際上它運行一個查詢,我檢查它在Rails的控制檯。請看下圖:

>> users = User.where(created_at: Time.now-7.days..Time.now).order(:created_at) 
User Load (0.5ms) SELECT "users".* FROM "users" WHERE ("users"."created_at" BETWEEN $1 AND $2) ORDER BY "users"."created_at" ASC [["created_at", 2016-11-11 09:59:00 UTC], ["created_at", 2016-11-18 09:59:00 UTC]] 
=> #<ActiveRecord::Relation [#<User id: 6, email: nil, first_name: nil, last_name: nil, username: "arslan_ali505", phone_number: nil, address: nil, created_at: "2016-11-14 16:02:27", updated_at: "2016-11-14 16:02:27", role_id: 7, temp_password: "P8ijrXZErI0=", temp_password_changed: false>, #<User id: 7, email: nil, first_name: nil, last_name: nil, username: "arslan_ali_arslan_ali170", phone_number: nil, address: nil, created_at: "2016-11-16 11:41:57", updated_at: "2016-11-16 18:58:37", role_id: 3, temp_password: "e27aad7b817354f3", temp_password_changed: true>, #<User id: 8, email: nil, first_name: "John", last_name: "Don", username: "jhondon213", phone_number: nil, address: nil, created_at: "2016-11-17 13:09:07", updated_at: "2016-11-17 13:09:43", role_id: 7, temp_password: nil, temp_password_changed: true>]> 
>> users.first 
=> #<User id: 6, email: nil, first_name: nil, last_name: nil, username: "arslan_ali505", phone_number: nil, address: nil, created_at: "2016-11-14 16:02:27", updated_at: "2016-11-14 16:02:27", role_id: 7, temp_password: "P8ijrXZErI0=", temp_password_changed: false> 
>> users.last 
=> #<User id: 8, email: nil, first_name: "John", last_name: "Don", username: "jhondon213", phone_number: nil, address: nil, created_at: "2016-11-17 13:09:07", updated_at: "2016-11-17 13:09:43", role_id: 7, temp_password: nil, temp_password_changed: true> 

+1

當你這樣做時,你可能想要觀察你的數據庫活動。然後重新考慮你的「不必運行兩個查詢」評論。 –

+2

該代碼還將運行兩個查詢。第一行返回一個ActiveRecord :: Relation對象;它不執行查詢。接下來的兩行將分別執行查詢,比如'... ORDER BY created_at LIMIT 1'和'... ORDER BY created_at DESC LIMIT 1' [[docs](http://api.rubyonrails.org/classes/ActiveRecord /FinderMethods.html))。這是一個很好的事情,因爲如果它實際上只運行一個查詢,它將獲取給定範圍內的所有記錄,可能是10,000或100,000或... –

+0

這是最高效的。查看評論 – slindsey3000

-1

您可以嘗試SQL查詢也&可以用它從使用Rails查詢直接四分五裂,將提高執行時間也。

ActiveRecord::Base.connection.execute("SQL query") 
相關問題