У меня две модели: posts
и likings
которые имеют отношения «один-ко-многим» (так что у одной записи много симпатий). Модель Likings также isActive
поле isActive
которое показывает, что симпатия активна или пассивна.
Я хочу получить (отсортировать) топ-5 сообщений, которые получили максимальные «активные» симпатии (только любит, чье isActive поле истинно, будет рассмотрено).
Это запрос:
select posts.*, count(likings.id) as likes_count from 'posts' left join 'likings' on 'likings'.'post_id' = 'posts'.'id' and 'likings'.'isActive' = 1 group by 'posts'.'id' order by 'likes_count' desc limit 5
который получается из этого запроса laravel:
Post::selectRaw('posts.*, count(likes.id) as likes_count') ->leftJoin('likes', function ($join) { $join->on('likes.post_id', '=', 'posts.id') ->where('likes.is_active', '=', 1); }) ->groupBy('posts.id') ->orderBy('likes_count', 'desc') ->take(5) ->get();
И это ошибка:
SQLSTATE[42000]: Syntax error or access violation: 1055 'database.posts.user_id' isn't in GROUP BY
Здесь posts.user_id
также является полем таблицы posts
и показывает владельца сообщения.
Как я могу устранить эту ошибку? Кажется, не логично изменять конфигурацию mysql (возможно, удаляя ONLY_FULL_GROUP_BY
режим), но минимальное изменение в запросе.
Каждое неагрегированное поле должно быть сгруппировано.
select posts.id, post.user_id, count(likings.id) as likes_count from posts left join likings on likings.post_id = posts.id and likings.isActive= 1 group by posts.id, posts.user_id order by likes_count desc limit 5
Или вы можете его aggregate
:
select posts.id, MIN(post.user_id), count(likings.id) as likes_count from posts left join likings on likings.post_id = posts.id and likings.isActive= 1 group by posts.id order by likes_count desc limit 5
Другой способ – изменить sql_mode
:
SET SESSION sql_mode = '';
Кроме того, вы можете разделить его на 2 запроса:
IN clause
) В 5.7 sqlmode устанавливается по умолчанию:
ONLY_FULL_GROUP_BY, NO_AUTO_CREATE_USER, STRICT_TRANS_TABLES, NO_ENGINE_SUBSTITUTION
Чтобы удалить предложение ONLY_FULL_GROUP_BY, вы можете сделать следующее:
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));