activerecordで最後のNレコードを取得するにはどうすればよいですか?


163

では:limit、クエリで、私は、最初のNレコードを取得します。最後のNレコードを取得する最も簡単な方法は何ですか?

回答:


143

このようなアクティブレコードクエリを実行すると、必要なものが得られると思います( 'Something'はモデル名です)。

Something.find(:all, :order => "id desc", :limit => 5).reverse

編集:コメントに記載されているように、別の方法:

result = Something.find(:all, :order => "id desc", :limit => 5)

while !result.empty?
        puts result.pop
end

データを2回注文する必要はないようです。現在、最初にカウントを取得し、それをオフセットで使用しています
JtR

それは私が考えていたもう1つの方法でしたが、データベースに対する1つのクエリではなく2つのクエリであるため、さらに多くの作業のように思われます。その時それ。(つまり、records.reverse.each do ..)
Dan McNevin

または、配列を逆にして、逆にするのではなく、Array.popを使用して配列を反復処理することはできません。ruby
Dan McNevin

1
Rails 3については、代わりにBongsの応答を参照してください。この方法は引き続き機能しますが、推奨される方法ではなくなりました。
カイルHeironimus

3
#find(:all)の呼び出しは廃止されました。代わりに#allを直接呼び出します。
Snowcrash 2013年

262

これはRails 3の方法です

SomeModel.last(5) # last 5 records in ascending order

SomeModel.last(5).reverse # last 5 records in descending order

4
Postgresでこれを試してください!私は確かに最初に問題がありました。SQLでは、指定しない限り順序は保証されませんが、MySQLはより寛容です。
Ghoti

5
注:これは、パフォーマンスの観点から、これを実装する良い方法ではありません-少なくともRails 3.1までは。SomeModel.last(5)は、selectステートメントを制限なしで実行し、SomeModelのすべてのレコードを配列としてRubyに返します。その後、Rubyは最後の(5)要素を選択します。効率的には、現在、制限を使用したい-特に潜在的に多くの要素がある場合。
DRobinson、2012

14
それはまさにそれがすべきことを行います:SELECT "items".* FROM "items" ORDER BY id DESC LIMIT 50
firedev

7
Rails 4では、ニックが言及したように、.last()によって生成されたクエリも最適です
Jimmie Tyrrell

1
SomeModel.last(5).class== なので、これはRails 4+では正しくありませんArray。正しいアプローチはSomeModel.limit(5).order('id desc')Arthur Nevesによるものであり、その結果SELECT \"somemodels\".* FROM \"somemodels\" ORDER BY id desc LIMIT 5
アミンアリアナ

50

Rails 3.1でそれを行う新しい方法は SomeModel.limit(5).order('id desc')


14
これはlast(5)、さらにチェーンするためのスコープを返すためよりも優れています。
lulalala

3
私はSomeModel.limit(100).reverse_orderRails 4(guides.rubyonrails.org/…)で使用していますが、同じです。
Ivan Black

@lulalalaが言及した「更なるチェーンのスコープ」の例:あなたは1列のみが必要な場合は、SomeModel.limit(5).order('id desc').pluck(:col)行いますSELECT SomeModel.col FROM SomeModel ORDER BY id desc LIMIT 5はるかに効率的にすべての列をつかみ、すべての廃棄よりもあるが、と1列SomeModel.last(5).map(&:col) したSELECT *代わりにSELECT col、あなたは、呼び出した後摘み取ることができません(最後;遅延評価チェーンは最後で終わります)。
Kanat Bolazar、2015

33

Rails 5(おそらくRails 4)

悪い:

Something.last(5)

なぜなら:

Something.last(5).class
=> Array

そう:

Something.last(50000).count

おそらくあなたの記憶を爆破するか、永遠にかかります。

良いアプローチ:

Something.limit(5).order('id desc')

なぜなら:

Something.limit(5).order('id desc').class
=> Image::ActiveRecord_Relation

Something.limit(5).order('id desc').to_sql
=> "SELECT  \"somethings\".* FROM \"somethings\" ORDER BY id desc LIMIT 5"

後者は未評価のスコープです。チェーンするか、を介して配列に変換でき.to_aます。そう:

Something.limit(50000).order('id desc').count

...少し時間がかかります。


1
そして実際はRails 3です。;)
ジョシュアピンター2018年

32

レール4とバージョン以上:

あなたがしたい場合は、このような何かを試すことができます最初の最も古いエントリを

YourModel.order(id: :asc).limit(5).each do |d|

最新の最新エントリが必要な場合は、このようなものを試すことができます

YourModel.order(id: :desc).limit(5).each do |d|

1
これは、受け入れられたものよりもRails 4の最新の回答のように見えます。:私は、最新の構文は次のようになりますことを考えるYourModel.all.order(id: :desc).limit(5)
jmarceli

@ user2041318:この新しい構文なしでありがとう" "
Gagan Gami

2
Order()はすべてのレコードを返します。YourModel.all.order()同じであるのでチェーンする必要はありませんYourModel.order()
フランシスコキンテロ2016

26

解決策はここにあります:

SomeModel.last(5).reverse

レールは怠け者なので、それは最終的にのようなSQLを使用してデータベースをヒットします: "SELECT table* FROM。table ORDER BY tableidDESC LIMIT 5"。


これは、次のすべてのレコードをロードしますSomeModel
John Hinnegan

より良いアプローチは、limit()です。これは効率的に見えません。
Anurag 2013年

3
@Developerは完全に正しいです。実行されたSQLは、SELECT table .* FROM table` ORDER BY tableでした。idDESC LIMIT 5`それはすべて選択を実行しませ
ddavison '23 / 11/15

4

結果に順序を設定する必要がある場合は、次を使用します。

Model.order('name desc').limit(n) # n= number

順序付けが不要で、テーブルに保存されたレコードのみが必要な場合は、次を使用します。

Model.last(n) # n= any number

4

私のRails (rails 4.2)プロジェクトでは、

Model.last(10) # get the last 10 record order by id

そしてそれは動作します。



2

ちょうど試して:

Model.order("field_for_sort desc").limit(5)

2
このソリューションが実行可能な理由を説明する必要があります。
Phiter

1

このクエリは、私が気に入っている "pluck"メソッドを使用する方が優れている/高速であることがわかりました。

Challenge.limit(5).order('id desc')

これにより、出力としてActiveRecordが提供されます。したがって、次のように.pluckを使用できます。

Challenge.limit(5).order('id desc').pluck(:id)

これにより、最適なSQLコードを使用しながら、IDを配列としてすばやく取得できます。


Challenge.limit(5).order('id desc').ids:)
公園。

0

Rails 3で昇順を指定するモデルのデフォルトスコープがある場合、上記のArthur Nevesで指定された順序ではなく、並べ替えを使用する必要があります。

Something.limit(5).reorder('id desc')

または

Something.reorder('id desc').limit(5)

0

N = 5で、モデルがMessageであるとします。次のようなことができます。

Message.order(id: :asc).from(Message.all.order(id: :desc).limit(5), :messages)

SQLを見てください。

SELECT "messages".* FROM (
  SELECT  "messages".* FROM "messages"  ORDER BY "messages"."created_at" DESC LIMIT 5
) messages  ORDER BY "messages"."created_at" ASC

キーは副選択です。最初に、必要な最後のメッセージを定義する必要があります。次に、メッセージを昇順に並べる必要があります。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.