MySQL中没有group by子句时的聚集函数

首先从一个无意中运行的例子讲起。数据表结构及数据如下(建表语句及插入语句就不提供了)。

看下面一段SQL语句及运行结果:

 从这个结果我们可以发现两件事情。第一,这条查询语句中没有group by子句,select子句中的非聚合字段没有出现在group by子句中,这与我们一贯的认知不同。类似语法的SQL查询语句在hive中是报错的(在MySQL也有可能报错,后面会详细说)。第二,这从这条语句的执行结果可以看出,SQL查询语句中的聚合函数字段执行完成,而非聚合字段似乎返回了满足where条件的第一条记录的order_id的值。但该order_id对应的(original_value-discount)的值并不是我们所求的max结果。

下面来分析一为什么会出现这中情况及结果。

通常MySQL5.7及以上版本中sql_mode是默认设置了ONLY_FULL_GROUP_BY模式的。一旦设置了该模式,会将两类SQL查询语句判定为不合法,具体如下:

  • 第1类,select子句、having子句、order by子句中的非聚合函数字段没有group by子句的查询语句。
  • 第2类,select子句、having子句、order by子句中的非聚合函数字段与group by 子句中字段没有函数依赖(functional dependency)。

再来看上面那段SQL语句,没有group by子句,也就意味着select 子句中的非聚合函数字段order_id没有出现在group by子句中,也就不存在函数依赖关系。所以我们可以推测我的MySQL的sql_mode中没有设置ONLY_FULL_GROUP_BY模式。但是在MySQL 5.7及以上版本中,ONLY_FULL_GROUP_BY模式是默认开启的,而关掉该模式可以在my.ini文件中修改sql_mode参数。具体如下:

MySQL8.0中的若是没有my.ini文件,可以参考https://www.cnblogs.com/RayWang/p/9347874.html 。

接着在看在关闭了ONLY_FULL_GROUP_BY模式下,会如何处理在其开启状态下判定为不合法的两类SQL查询语句。

  • 首先,非聚合字段没有出现在group by 子句中。

如果select子句中有未出现在group by子句中的普通字段,这是服务器或从每个组中随机选择一个值输出。

此时,上述SQL查询语句等价于如下代码:

  • 其次,非聚合字与group by中的字段不存在函数依赖关系。

先来看看什么是函数依赖。MySQL函数依赖是指:X能够决定Y,即当X确定之后,Y也就确定了,则我们说Y函数依赖X。 以下面代码为例:

 从对原始数据的分析中可以发现,order_id其实是表的主键,那自然当按order_id进行分组之后,就已经在每个分组内部完成了cust_id的分组。所以上述代是可以运行的。但是字段之间的函数依赖只能基于键,基于相等性及基于视图建立。其他情况,及时X唯一确定了一个Y,也不能算是函数依赖。如下:

在上述SQL代码中,一个city,只会对一个area,但仍然提示1055错误。

参考资料:

1. https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

2. https://dev.mysql.com/doc/refman/5.7/en/group-by-functional-dependence.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值