Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

dionarap's avatar

Order by AVG on a tagging system.

I have a tagging system on my site and clicking on a tag will take you to a list associated of items associated with that tag. I want to order these items(batsmen) on the highest avg 'rating' score they have been given by users who have reviewed them, so the top rated batsmen associated with the tag shows first. How would i do this?

My tables:

  • Batsmen : id, name, Country_id,
  • Reviews: id, rating, comment, Batsmen_id
  • tag: id, tagname
  • Batsmen_tag(many to many table): batsmen_id, Tag_id

Currently i am just finding all on tag($id) in my Tag controller and using a foreach with the relationship to bring back batsmen related to that tag, for example

@foreach($tag->batsmen as $tags)

@endforeach
0 likes
4 replies
Dry7's avatar

try

$batsmens = $tag->batsmen->sortByDesc(function ($item) { return $item->reviews->max('rating'); });

@foreach($batsmens  as $batsmen)

@endforeach
dionarap's avatar

Ive tried this and it just returns the batsmen like usual but the order by highest avg rating part does not seem to work

michaelberry's avatar

I don't think I know enough to get you from where you are to where you're going, but maybe I can help along the path.

To get an average 'rating' with normal SQL select the average column and then you would use Group By clause and then to order it by descending order, use the Order By clause. For example:

SELECT b.name, avg('r.rating') 
FROM batsmen b
LEFT INNER JOIN batsmen_tag bt ON bt.Tag_id = b.batsmen_id
LEFT INNER JOIN reviews r ON r.Batsmen_id = bt.batsmen_id
GROUP BY b.name
ORDER BY avg(r.rating) desc

Now all you have to do is translate your SQL into Eloquent calls for Laravel (or you can always use Raw Expressions). Something like this, maybe:

$batsmen = DB::('batsmen')
    ->leftJoin('batsmen_tag', 'batsmen.id', '=', 'batsmen_tag.batsmen_id')
    ->leftJoin('reviews', 'batsmen.id', '=', 'reviews.batsmen_id')
    ->select('DB::raw('avg('reviews.rating') as rating, batsmen.name'))
    ->groupBy('batsmen.name')
    ->orderBy('rating', 'desc')
    ->get();

Here are a couple other resources that may help:

https://stackoverflow.com/questions/44661388/how-to-order-by-an-average-rating

https://laracasts.com/discuss/channels/eloquent/orderby-computed-related-attribute

https://laravel.io/forum/03-01-2014-use-avg-in-eloquent-for-orderby

1 like
dionarap's avatar

Thanks for the replies so far, ive tried those suggested and none of them work. Some more information on this, i can pull back batsmen and order by highest average i do this like this

Please or to participate in this conversation.