Reputation: 439
I understand that this seems to be a documented mySQL question. However, I found no Eloquent solution to get the ranks of rows in an orderBy query. Here is what I want.
I have a table that looks like this
id | number
-----------
1 | 30
2 | 24
3 | 4
4 | 45
I am able to order the number column this query:
Number::orderBy('number', 'desc')->get();
However, I want to retrieve the rank of each row. So the row that has the id of 4 (with the number of 45) would have a rank of 1. The row with the id of 1 (and the number of 30) would have the rank of 2.
What is the best way to get the rank of a row with Eloquent queries?
Upvotes: 1
Views: 3124
Reputation: 29
For laravel's Eloquent... Add this to your model. Unleash the greatness of T.Otwells Eloquent ;)
public function getPostionAttribute()
{
return $this->newQuery()->where('number', '>=', $this->number)->count();
}
Upvotes: 3
Reputation: 81187
In MySQL you can rely on this (rename row to rank if you like) to get multiple records instead of querying per model:
// any Model, model trait or whatever you like
// for convenience wrapped in scope
public function scopeGetWithRowNumber($query, $columns = ['*'])
{
// Set the row number
$offset = (int) $query->getQuery()->offset;
DB::statement(DB::raw("set @row={$offset}"));
// Adjust SELECT clause to contain the row
if ( ! count($query->getQuery()->columns)) $query->select($columns);
$sub = $query->addSelect([DB::raw('@row:=@row+1 as row')]);
// Return the result instead of builder object
return $query->get();
}
Then use however you'd run any query:
Number::getWithRowNumber(); // SELECT * + row attribute starting from 1
Number::take(25)->skip(2500)->getWithRowNumber(); // SELECT * + row 2501+
Number::latest()->getWithRowNumber(['id','number']); // SELECT id, number + row 1+
Number::orderBy('number','desc')->getWithRowNumber(); // example from your question
Upvotes: 1
Reputation: 6294
Well it's quite simple really, what you currently have will work.
$i = 1;
$numbers = Number::orderBy('number', 'desc')->get();
foreach($numbers as $number)
{
echo $i . ' ' . $number->id;
$i++;
}
Upvotes: 0