mysql 查询提示 SELECT list is not in GROUP BY clause and contains nonaggregated column 'user_login.user_name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by 是为什么?

mysql 5.7之后,对group by的处理有所区别,这里基于一个demo做一些探究

官方文档:

需求

统计用户登录次数,显示用户Id和姓名,如下:

基于上面的需求,假设目前只有一张'用户登录日志表'可用:

DROP TABLE

IF EXISTS user_login;

CREATE TABLE `user_login` (

`id` INT (11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',

`user_id` INT (11) DEFAULT NULL COMMENT '用户Id',

`user_name` VARCHAR (100) DEFAULT NULL COMMENT

'用户姓名(冗余:可变性不大,业务要求不严)',

`login_time` datetime DEFAULT NULL COMMENT '登录时间',

PRIMARY KEY (`id`)

) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8 COMMENT = '用户登录日志表';

INSERT INTO `user_login` ( `user_id`, `user_name`, `login_time`)

VALUES ( '1', '小A', '2017-09-13 22:06:49');

INSERT INTO `user_login` ( `user_id`, `user_name`, `login_time`)

VALUES ( '1', '小A', '2017-09-14 12:06:51');

INSERT INTO `user_login` ( `user_id`, `user_name`, `login_time`)

VALUES ( '2', '小B', '2017-09-14 16:16:54');

直观数据如下:

问题

先从下面这条实现需求的 sql 谈起:

-- SELECT 后面 包含了GROUP BY 后面没有的一个列 user_name

SELECT user_id,user_name,count(*) FROM user_login GROUP BY user_id;

上面的sql,给人的第一感就是语法会报错,尤其对于部分从oracle过渡到mysql的人。

真实情况是什么样呢?

默认设置下,在mysql 5.7之前,上面sql的语法是正确的,之后的版本才会报错,如下:

SELECT list is not in GROUP BY clause and contains nonaggregated column 'user_login.user_name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

-- SELECT 后面包含了非聚合的列user_name,而user_name和GROUP BY 后面的列没有函数依赖关系;这个违背了only_full_group_by的sql模式

当然在GROUP BY后面带上列user_name,肯定ok,就不说了,这里我们来探究一下mysql 5.7 之后给出了哪些解决方案。从报错提示中似乎可以得知,如果user_name和user_id之间functionally dependent,就ok,关于什么是functionally dependent,后面再说,这里先说一下mysql的only_full_group_by模式 。

only_full_group_by

Reject queries for which the select list, HAVING condition, or ORDER BY list refer to nonaggregated columns that are neither named in the GROUP BY clause nor are functionally dependent on (uniquely determined by) GROUP BY columns.

-- select、HAVING、ORDER BY 后面不能出现‘非聚合的列’(GROUP BY后面没有的列),除非这些非聚合列和GROUP BY后面的列之间‘函数依赖’(唯一决定) .

mysql 5.7之后,默认开启了only_full_group_by的sql模式,通过命令可以查看:

-- 查看全局的sql_mode

SELECT @@GLOBAL .sql_mode;

-- 查看当前会话的sql_mode

SELECT @@SESSION.sql_mode;

-- 结果如下,第一个就是ONLY_FULL_GROUP_BY

ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,

NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,

NO_ENGINE_SUBSTITUTION

正是因为only_full_group_by的约束,sql才会报错,关闭即可解决问题。

把上面查询出的sql_mode的值,去掉ONLY_FULL_GROUP_BY一项,重新设置一下,2种关闭方式:

SET SESSION sql_mode = 'modes';-- 仅对当前会话有效

SET GLOBAL sql_mode = 'modes'; -- 全局有效

-- 设置当前session的sql_mode

SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,

NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,

NO_ENGINE_SUBSTITUTION';

-- 设置之后,在当前session下,下面的sql不再会报错:

SELECT user_id,user_name,count(*) FROM user_login

GROUP BY user_id;

此外还可以通过配置文件来修改sql_mode,这里不探究 ,接下来简单说一下上面提到函数依赖。

functionally dependent

functionally dependent(函数依赖) 等同于 uniquely determined(唯一决定) ,简单理解就是,一个字段完全依赖于另一个字段,即其值由另一个字段来决定。比如,一个表的非主键列 uniquely determined by 主键列,我们就可以称它们为函数依赖。

基于上面的测试场景,假设我们还有一张‘用户表‘:

CREATE TABLE `user` (

`id` INT (11) NOT NULL AUTO_INCREMENT,

`name` VARCHAR (64) DEFAULT NULL COMMENT '

姓名(和主键id函数依赖)',

PRIMARY KEY (`id`)

) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT '用户表';

INSERT INTO `user` VALUES (1, '小A');

INSERT INTO `user` VALUES (2, '小B');

显然用户name列 functionally dependent on 用户id列,所以下面的sql任何时候都语法正确:

SELECT

ul.user_id,

u.name, -- 这一列虽然不是聚合列,

-- 但是它和主键u.id是函数依赖的,所以整个sql都ok

count(*)

FROM

user_login ul

INNER JOIN user u ON ul.user_id = u.id

GROUP BY

ul.user_id;

.

any_value

如果多出的非聚合列没有functionally dependent特性,而且我们也不想修改默认的sql_mode的话,  mysql还为我们提供了另一种解决方案,即通过函数any_value,来绕过only_full_group_by模式,如下:

-- any_value会随便选取一个user_name值,通常是第一个

SELECT user_id,any_value(user_name),

count(*) FROM user_login GROUP BY user_id;

.

规范

有人会说,费这么大劲干啥呢,直接在最后面补上user_name列不就ok了么,而且这样写也是理所当然:

-- 符合SQL99规范的group by

SELECT user_id,user_name,count(*) FROM user_login

GROUP BY user_id,user_name;

确实如此,实际工作中,除非在升级mysql版本之后,发现一些历史遗留的sql出错时,我们才有必要考虑如何去解决这些问题。正常情况下,我们只需要按照 only_full_group_by 的规范来开发就行了,即select、having、order by这些关键字后面的列必须同时出现在group by后面,除非多出的非聚合列和group by后面的列有函数依赖关系。

以上就是关于 mysql报错之5.7版本的 group by mysql不能使用group by 的全部内容了,喜欢的小伙伴别忘了点赞分享一下哦,关注优讯网,优讯有你更精彩!

转载自: https://my.oschina.net/xsh1208/blog/3107161

版权归原作者所有,如有侵权请联系我们删除。

mysql group b_mysql报错之5.7版本的 group by mysql不能使用group by相关推荐

  1. MySQL插入汉字报错的解决方案

    MySQL插入汉字报错的原因是字符集的问题,MySQL默认使用的是Latin(拉丁文)字符集,可以在创建数据库时指定其字符集:CREATE DATABASE test DEFAULT CHARACTE ...

  2. mysql group by 报错 ,only_full_group_by 三种解决方案

    mysql group by 报错 ,only_full_group_by 三种解决方案 参考文章: (1)mysql group by 报错 ,only_full_group_by 三种解决方案 ( ...

  3. mysql not in报错_mysql从5.7升级到8.0查询报错Expression #2 of SELECT list is not in GROUP BY...

    报错信息: Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'sss. ...

  4. In aggregated query without GROUP BY报错

    记录一下关于mysql的一个报错问题解决方案:In aggregated query without GROUP BY, expression #1 of SELECT list contains n ...

  5. group by 报错 出现In aggregated query without

    记录一下关于mysql的一个报错问题解决方案: In aggregated query without GROUP BY, expression #1 of SELECT list contains ...

  6. kettle使用mysql作为资源库报错 创建资源库时只有25张表,原本应该46张表。

    kettle使用mysql作为资源库报错 创建资源库时只有25张表,原本应该46张表. 连用户表都没有 ,导致连 默认的 admin和guest都无法登陆自己的资源库!!!! 问题是 SQL语句里边使 ...

  7. mysql语句delete报错_「delete语句」MySQL——DELETE语句中的坑 - seo实验室

    delete语句 在网上搜索了一个mysql数据库删除重复数据的sql,原文是这样的: DELETE FROM people WHERE peopleName IN ( SELECT peopleNa ...

  8. MySQL5.7.5及以上执行group by报错

    MySQL执行报错: [Err] 1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggre ...

  9. mysql安装教程博音网_RTSP视频平台EasyNVR使用mysql数据源启动报错unknow drivermysql优化...

    原标题:RTSP视频平台EasyNVR使用mysql数据源启动报错unknow driver"mysql"优化 我们上一篇讲了TSINGSEE青犀视频开发的视频平台默认都是使用的s ...

最新文章

  1. 上海交大、华为海思提出X-volution,发力网络核心基础架构创新
  2. Python 中多线程共享全局变量的问题
  3. 三星s窗口共享android,三星s窗口共享(SideSync pc端)
  4. OpenStack、KVM、Docker——Docker之后还需要OpenStack吗?
  5. 1.3 使用电脑测试MC20的电话语音功能
  6. Java Date hashCode()方法与示例
  7. CVPR2020 | 华为GhostNet超越谷歌MobileNetV3
  8. LeetCode-226. 翻转二叉树
  9. python把数字阿拉伯数字转换成中文10以内_Python实现把数字转换成中文
  10. mongodb笔记2
  11. 数字公式识别的学习笔记
  12. python解释器调用_Python3.x那些事儿:[2]如何调用解释器-百度经验
  13. Word2Vec入门
  14. jquery 如何控制滚动条每次向下滚动300px
  15. Navicat连接CentOS7中的MariaDB
  16. 浪潮“151计划”:信息安全 没有“偏远地区”
  17. 通达信版弘历软件指标_通达信仿弘历软件的六彩神龙指标公式副图源码
  18. 从福彩官网抓取 双色球历史数据
  19. 安装win7时缺少所需的CDDVD驱动器设备驱动程序
  20. 第十一届蓝桥杯b组(10月真题)

热门文章

  1. 30个实用的 Photoshop 动作《免费下载》
  2. Linux下后台执行java程序
  3. 修改environment导致重启不能登录的问题解决
  4. Python标准库datetime中4种基本对象的用法
  5. 详解Python线程对象daemon属性对线程退出的影响
  6. Python查找包含指定字符串的所有文件
  7. 微课|中学生可以这样学Python(例7.3):栈
  8. 微课|中学生可以这样学Python(2.3.3节):filter()函数
  9. 微课|中学生可以这样学Python(2.2.1节):算术运算符
  10. 转义字符'\r'在Python内置函数print()中的妙用