我有2张桌子的注释和图片
我正在尝试先订购具有图像的评论,然后再订购不含图像的评论。
我在下面使用此查询解决了此问题,但是对于大数据来说它非常慢,大约需要12秒
$data = Comment::withCount([
'images' => function ($query) use ($shop)
{
$query->where('shop_name', $shop);
},
])->where('shop_name', $shop)->orderBy('images_count', 'desc')->paginate(10);
如何提高性能,或者是否有其他方法可以更快地获得相似的结果?
答案 0 :(得分:1)
问题在于Laravel如何使withCount()
起作用-它将生成如下内容:
SELECT `comments`.*,
(SELECT Count(*)
FROM `images`
WHERE `comment_id`.`id` = `comments`.`id`
AND `images`.`shop_name` = 'your shop') AS `images_count`
FROM `comments`
WHERE `shop_name` = 'your_shop'
ORDER BY `images_count`
这将强制MySQL对指定商店的每个评论执行count()
子查询。
您在这里需要做的是将这个 correlated 子查询(针对每一行执行)变成一个 independent 查询(仅执行一次),然后利用联接让MySQL全部配对:
$imagesCountQuery = DB::table('comments')
->selectRaw('comments.id AS comment_id, COUNT(comments.id) AS images_count')
->join('images', 'images.comment_id', '=', 'comments.id') /* !!! */
->where('images.shop_name', '=', $shop)
->groupBy('comments.id');
$data = Comment::joinSub($imagesCountQuery, 'images_count_sub', function ($join) {
$join->on('comments.id', '=', 'images_count_sub'.'comment_id'); /* !!! */
})->where('shop_name', $shop)->orderBy('images_count_sub.images_count', 'desc')->paginate(10);
!!! -应该修改此行以表示您的评论的images
关系。在此示例中,我假设这是hasMany
关系,因为您没有在问题中指出这一点。
答案 1 :(得分:0)
您需要在Comment模型中创建hasMany关系。
class Comment extends \Eloquent {
public function images()
{
return $this->hasMany('Images', 'comment_id');
}
}
现在您可以使用下面的查询来获取记录。
$comments = Comments::with('images')->get()->sortBy(function($comment)
{
return $comment->images->count();
});