我的数据库中有2个表。
books
和ratings
在books
中
id
,name
在ratings
id
,book_id
,rating
我为这些模型设置了很多关系。
在Book
模型中-
public function ratings()
{
return $this->hasMany('App\Rating');
}
在Rating
模型中-
public function book()
{
return $this->belongsTo('App\Book');
}
现在,我想获取所有具有平均评分但按高评分排序的图书。
所以我首先评价高的书,然后评价低的书。
所以我如何联接2个表以实现此结果。
谢谢。
答案 0 :(得分:3)
您可以使用修改后的withCount()
:
$books = Book::withCount(['ratings as average_rating' => function($query) {
$query->select(DB::raw('coalesce(avg(rating),0)'));
}])->orderByDesc('average_rating')->get();
答案 1 :(得分:0)
该查询看起来像这样:
SELECT book.id, AVG(ratings.rating) AS avg_rating
FROM ratings
JOIN book ON book.id = ratings.book_id
/* WHERE AVG(ratings.rating) > 4 You could say only return results where rating > 4 */
GROUP BY book.id
ORDER BY AVG(ratings.rating) DESC LIMIT 5;
您需要将两个表连接起来,在书上使用带有group by的聚合函数。然后只需排序并限制结果即可。
更新:
针对您的问题:
SELECT book.id, COALESCE(AVG(ratings.rating), 0) AS avg_rating
FROM book
*LEFT* JOIN ratings ON book.id = ratings.book_id
GROUP BY book.id
ORDER BY AVG(ratings.rating);
使用view
可能会在简化ORM和查询的合理性之间做出折衷。
答案 2 :(得分:0)
通过Collections *
$books = Book::with('ratings')
->get()
->sortBy(function($bk, $key) {
if($bk->rating) {
return $bk->rating->rating;
}
return null;
});
通过加入
$books = Book::join('rating', 'rating.book_id', '=', 'book.id')
->orderBy('ratings.rating', 'desc')
->select('books.*')
->get();
答案 3 :(得分:0)
Books::withAvg('ratings', 'rating')->orderBy('ratings_avg_rating', 'desc')->take(5)->get();
这适用于 Laravel 8