Самый быстрый способ заказа таблицы по столбцу связанной таблицы - PullRequest
3 голосов
/ 18 июня 2019

У меня есть 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);

Как я могу улучшить производительность или есть другой способ получить аналогичные результаты более быстрым способом?

Ответы [ 2 ]

1 голос
/ 18 июня 2019

Проблема заключается в том, как 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() подзапрос для каждого комментария указанного магазина.

Здесь нужно сделать этот коррелированный подзапрос (который выполняется для каждой строки) в независимый запрос (который выполняется только один раз), а затем использовать соединения, чтобы 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, поскольку вы не указали это в своем вопросе.

0 голосов
/ 18 июня 2019

вам нужно создать отношение 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();
    });
...