Как выполнить такой sql запрос в laravel 5.3?

SELECT sum(likes.like)
	FROM places left OUTER JOIN media_items ON places.id = media_items.place_id
    left OUTER JOIN likes ON media_items.id = likes.likeable_id
	WHERE likes.likeable_type = 'App\\MediaItem'
	AND places.id = 1;


вот такой запрос должен посчитать сумму лайков для определенного можно сказать альбома с фотографиями где у каждой фотографии своя сумма лайков. Но как его выполнить в контексте latavel не разобрался, пробывал так:

public function getRatingAttribute()
    {


        $sql = "SELECT sum(likes.like)
	FROM places left OUTER JOIN media_items ON places.id = media_items.place_id
    left OUTER JOIN likes ON media_items.id = likes.likeable_id
	WHERE likes.likeable_type = 'App\\MediaItem'
	AND places.id = 1;";

        $result = DB::connection()->getPdo()->exec($sql);
        
        return $result;


    }


Пытался сделать это связями laravel, но получилось слишком много запросов при выводе списка альбомов чтобы сортировать их по рейтингу, который складывается из суммы лайков для самого альбома и суммы всех вложенных лайков для каждой вложенной в него фотографии.

вот так изначально было:
public function getRatingAttribute()
    {
        $mediaItems = $this->mediaItems;
        $result = 0;
        $result += $this->likes->sum('like');

        foreach ($mediaItems as $mediaItem) {
            $result += $mediaItem->likes->sum('like');
        }
        
        return $result;
    }


- это естественно дает слишком много запросов.

В идеале понять как сделать нормальное количество запросов используя стандартные связи laravel. Ну или хотя бы как выполнить чистый sql запрос выше и в него воткнуть динамические данные.
  • Вопрос задан
  • 312 просмотров
Решения вопроса 1
Для начала стоит определиться, какую задачу решить надо: Как еще можно написать запрос? Как его написать "более стандартным функционалом Laravel"? Или же как сделать его быстрее? Или же как сделать меньше запросов?

Исходя из этих ответов, нужно выстраивать по разному решение.
Если не нравится ->exec(), то можно завернуть в DB::raw.

Ваше "изначальное" решение можно переписать через lazy load
$mediaItems = $this->mediaItems;
$mediaItems->load('likes')

        $result = 0;
        $result += $this->likes->sum('like');

        foreach ($mediaItems as $mediaItem) {
            $result += $mediaItem->likes->sum('like');
        }
        
        return $result;


Это уже сделает запросов меньше.

После посмотреть на структуру БД, посмотреть на загрузку. Может быть есть смысл либо кэшей прикрутить, если она больше Read чем write. Либо может денормализацию сделать или вообще вынести в отдельную красивую таблицу данные под этот запрос и свести ваш запрос к
SELECT like
FROM reports_likes
WHERE type = 'App\\MediaItem'
AND place_id = 1;
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
arutyunov
@arutyunov
Mooza.ru — Делаем сайты
А чем raw expressions из документации не подходят?
Ответ написан
@miki131
Покажите структуру БД и связи в Laravel.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы