【问题标题】:How to resolve "isn't in GROUP BY" error in mysql query如何解决mysql查询中的“不在GROUP BY”错误
【发布时间】:2016-02-09 01:33:18
【问题描述】:

我有两个模型:postslikings,它们具有一对多的关系(因此,一个帖子有很多赞)。 Likings 模型还有一个isActive 字段,显示喜欢是主动的还是被动的。

我想获得(排序)获得最多“活跃”赞的前 5 个帖子(仅考虑 isActive 字段为 true 的赞)。

这是查询:

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模式),但查询的最小更改。

【问题讨论】:

  • 按照标准,您必须列出group clause 中的每个选定字段或使用聚合函数之一。

标签: php mysql laravel


【解决方案1】:

每个非聚合字段都应该分组。

这是标准行为,在 mysql 中,取决于 ONLY_FULL_GROUP_BY 模式。
此模式在 >= 5.7 中默认启用。

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个查询:

  1. 获取聚合和发布 ID
  2. 使用获取的 id 获取帖子数据(使用 IN clause

【讨论】:

  • 我需要帖子的所有字段。我不能用帖子开始查询吗?*
  • 可以,但不能在group子句中进行。其他选项是在mysql 配置或会话中更改sql_mode
  • 也许我应该多写一个查询。
  • 此错误的最佳答案,所有其他答案(在其他主题中)建议禁用 config database.strict。你可以通过使用 ->groupBy('posts.id','posts.user_id') 来做到这一点。
  • 那是什么鬼?我不明白为什么这应该是默认行为?为什么?
【解决方案2】:

在 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',''));

【讨论】:

  • 如果我们这样做会不会导致任何问题?
  • 为什么这是默认设置?是什么原因?
  • 因为不完整的 group by 实际上没有意义。如果您确定,您在分组子集中具有唯一值,只需将其添加到分组中,如果没有,那么 dbms 怎么能正确?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-29
  • 2013-03-10
  • 1970-01-01
相关资源
最近更新 更多