Laravel查询问题:返回所有餐厅并将无评分餐厅平均评分为0
解决方法
要让所有餐厅都返回,并且把无评论餐厅的average_rating设为0,你需要做两个关键调整:
- 用
COALESCE()函数把AVG(reviews.rating)的NULL值转换成0,这样无评论的餐厅平均分会被计算为0。 - 在
havingRaw条件中也使用COALESCE(),确保0值能被你的评分范围过滤逻辑包含进去。
修改后的完整查询代码如下:
<?php $query = $this->restaurant->leftJoin('reviews', 'reviews.restaurant_id', '=', 'restaurants.id'); $query = $user_id == null ? $query : $query->where("user_id", $user_id); $query = $query->select('restaurants.*') ->selectRaw('ROUND(COALESCE(AVG(reviews.rating), 0), 1) as average_rating') ->groupBy('restaurants.id') ->havingRaw('COALESCE(AVG(reviews.rating), 0) >= ?', [$request->from_rating]) ->havingRaw('COALESCE(AVG(reviews.rating), 0) <= ?', [$request->to_rating]) ->orderByDesc("average_rating") ->paginate( $this->perPage, ['id', 'name', 'image', 'description', 'filesystem', 'created_at'], 'page', $request->page ); return $query;
为什么这样有效?
- 你的原始查询中,没有评论的餐厅的
AVG(reviews.rating)结果是NULL,而NULL在比较运算(>=/<=)中会返回false,所以这些餐厅被havingRaw过滤掉了。 COALESCE(AVG(reviews.rating), 0)会把NULL替换成0,这样无评论餐厅的平均分会被设为0,同时在having条件中,0会参与评分范围的判断(只要你的from_rating≤0且to_rating≥0,这些餐厅就会被保留)。
额外提示
如果你的评分范围可能不包含0(比如用户筛选的是1-5分),那无评论的餐厅还是会被过滤掉——这符合业务逻辑,但如果你希望无论评分范围如何都返回所有餐厅,那你需要调整having条件,把COALESCE(...)的判断改成:要么符合评分范围,要么原始的AVG(reviews.rating)是NULL(也就是无评论)。比如:
->havingRaw('(COALESCE(AVG(reviews.rating), 0) >= ? AND COALESCE(AVG(reviews.rating), 0) <= ?) OR AVG(reviews.rating) IS NULL', [$request->from_rating, $request->to_rating])
这样无论用户筛选的评分范围是什么,无评论的餐厅都会被返回,且平均分为0。
内容的提问来源于stack exchange,提问作者Nika Kurashvili
相关产品推荐
相关产品推荐

