92

I have table of dogs in my DB and I want to retrieve N latest added dogs.

Only way that I found is something like this:

Dogs:all()->where(time, <=, another_time);

Is there another way how to do it? For example something like this Dogs:latest(5);

Thank you very much for any help :)

Kevin
  • 41,694
  • 12
  • 53
  • 70
Jakub Kohout
  • 1,854
  • 3
  • 21
  • 36
  • A combination of the `orderBy()` and `limit()` methods; though you do also have `latest()` as an alternative to `orderBy()` – Mark Baker Jul 21 '14 at 08:51
  • [Google is your friend](http://forumsarchive.laravel.io/viewtopic.php?id=16126). – Vucko Jul 21 '14 at 08:54

13 Answers13

189

You may try something like this:

$dogs = Dogs::orderBy('id', 'desc')->take(5)->get();

Use orderBy with Descending order and take the first n numbers of records.

Update (Since the latest method has been added):

$dogs = Dogs::latest()->take(5)->get();
The Alpha
  • 143,660
  • 29
  • 287
  • 307
  • What happens if there are only 3 records in this case? – f7n Feb 03 '17 at 11:33
  • 5
    You'll get three :-) – The Alpha Feb 03 '17 at 12:21
  • 1
    This will reverse order of your items. You will have to re-order them in your application. So if you're trying to load last 5 posts sorted by date, don't forget to re-sort them on collection level. – TrueStory Aug 12 '19 at 13:54
  • @TheAlpha I want to fetch from desc but I want to skip the latest 10000 records. Record I want is included in last 20000 but surely not in the latest 10000. Any thoughts? – gowlemn Aug 15 '22 at 19:49
  • 1
    @gowlemn, try `Dogs::latest()->skip(10000)->take(10000)->get(); `. – The Alpha Aug 15 '22 at 21:19
43

My solution for cleanliness is:

Dogs::latest()->take(5)->get();

It's the same as other answers, just with using built-in methods to handle common practices.

parker_codes
  • 3,267
  • 1
  • 19
  • 27
  • 4
    This also works with UUIDs so it's more generic. It doesn't work with tables that don't have timestamps though. – iSWORD Sep 16 '19 at 15:57
11
Dogs::orderBy('created_at','desc')->take(5)->get();
Luca C.
  • 11,714
  • 1
  • 86
  • 77
10

You can pass a negative integer n to take the last n elements.

Dogs::all()->take(-5)

This is good because you don't use orderBy which is bad when you have a big table.

João Marcus
  • 101
  • 1
  • 4
6

You may also try like this:

$recentPost = Article::orderBy('id', 'desc')->limit(5)->get();

It's working fine for me in Laravel 5.6

Bablu Ahmed
  • 4,412
  • 5
  • 49
  • 64
  • Yes, method `take` and `limit` is similar. The parent is `limit`, and `take` is just alias. You can check on file Builder.php – ibnɘꟻ Sep 12 '18 at 13:12
2

I use it this way, as I find it cleaner:

$covidUpdate = COVIDUpdate::latest()->take(25)->get();
hackernewbie
  • 1,606
  • 20
  • 13
1

Ive come up with a solution that helps me achieve the same result using the array_slice() method. In my code I did array_slice( PickupResults::where('playerID', $this->getPlayerID())->get()->toArray(), -5 ); with -5 I wanted the last 5 results of the query.

levi
  • 1,566
  • 3
  • 21
  • 37
1

The Alpha's solution is very elegant, however sometimes you need to re-sort (ascending order) the results in the database using SQL (to avoid in-memory sorting at the collection level), and an SQL subquery is a good way to achieve this.

It would be nice if Laravel was smart enough to recognise we want to create a subquery if we use the following ideal code...

$dogs = Dogs::orderByDesc('id')->take(5)->orderBy('id')->get();

...but this gets compiled to a single SQL query with conflicting ORDER BY clauses instead of the subquery that is required in this situation.

Creating a subquery in Laravel is unfortunately not simply as easy as the following pseudo-code that would be really nice to use...

$dogs = DB::subQuery( 
    Dogs::orderByDesc('id')->take(5) 
)->orderBy('id');

...but the same result can be achieved using the following code:

$dogs = DB::table('id')->select('*')->fromSub(
    Dogs::orderByDesc('id')->take(5)->toBase(), 
    'sq'
)->orderBy('id');

This generates the required SELECT * FROM (...) AS sq ... sql subquery construct, and the code is reasonably clean in terms of readability.)

Take particular note of the use of the ->toBase() function - which is required because fromSub() doesn't like to work with Eloquent model Eloquent\Builder instances, but seems to require a Query\Builder instance). (See: https://github.com/laravel/framework/issues/35631)

I hope this helps someone else, since I just spent a couple of hours researching how to achieve this myself. (I had a complex SQL query builder expression that needed to be limited to the last few rows in certain situations).

1

For getting last entry from DB

$variable= Model::orderBy('id', 'DESC')->limit(1)->get();

1

Can use this latest():

$dogs = Dogs::latest()->take(5)->get();
James Risner
  • 5,451
  • 11
  • 25
  • 47
0

Imagine a situation where you want to get the latest record of data from the request header that was just inserted into the database:

$noOfFilesUploaded = count( $request->pic );// e.g 4
$model = new Model;

$model->latest()->take($noOfFilesUploaded); 

This way your take() helper function gets the number of array data that was just sent via the request.

You can get only ids like so:

$model->latest()->take($noOfFilesUploaded)->puck('id')

Dharman
  • 30,962
  • 25
  • 85
  • 135
jovialcore
  • 601
  • 1
  • 5
  • 13
0
use DB;

$dogs = DB::select(DB::raw("SELECT * FROM (SELECT * FROM dogs ORDER BY id DESC LIMIT 10) Var1 ORDER BY id ASC"));
Rejneesh
  • 1,574
  • 16
  • 16
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the [help center](https://stackoverflow.com/help/how-to-answer). – Lizesh Shakya Oct 06 '21 at 07:52
0
Dogs::latest()->take(1)->first();

this code return the latest record in the collection

MostafaHashem
  • 127
  • 2
  • 3