MySQL中无GROUP BY情况下直接使用HAVING语句的问题探究

这篇文章主要介绍了MySQL中无GROUP BY情况下直接使用HAVING语句的问题探究,同时探究了该情况下MAX与MIN功能的使用情况,需要的朋友可以参考下:

今天有同学给我反应,有一张表,id是主键,这样的写法可以返回一条记录:

“SELECT * FROM t HAVING id=MIN(id);”

但是只是把MIN换成MAX,这样返回就是空了:

“SELECT * FROM t HAVING id=MAX(id);”

这是为什么呢?

我们先来做个试验,验证这种情况。

这是表结构,初始化两条记录,然后试验:

初看之下,好像真的是这样哎,怎么会这样呢?

我再试一下,把a字段改一个为10,然后试下a字段:

我擦,这回MAX能返回,MIN不能了,这又是为啥呢?

旁白

一般来说,HAVING子句是配合GROUP BY使用的,单独使用HAVING本身是不符合规范的,

但是MySQL会做一个重写,加上一个GROUP BY NULL,”SELECT * FROM t HAVING id=MIN(id)”会被重写为”SELECT * FROM t GROUP BY NULL HAVING id=MIN(id)”,这样语法就符合规范了。

继续……

但是,这个 GROUP BY NULL 会产生什么结果呢?经过查看代码和试验,可以证明,GROUP BY NULL 等价于 LIMIT 1:

也就是说,GROUP BY NULL 以后,只会有一个分组,里面就是第一行数据。

但是如果这样,MIN、MAX结果应该是一致的,那也不应该MAX和MIN一个有结果,一个没结果啊,这是为什么呢,再做一个测试。

修改一下数据,然后直接查看MIN/MAX的值:

是不是发现问题了?

MAX/MIN函数取值是全局的,而不是LIMIT 1这个分组内的。

因此,当GROUP BY NULL的时候,MAX/MIN函数是取所有数据里的最大和最小值!

所以啊,”SELECT * FROM t HAVING id=MIN(id)”本质上是”SELECT * FROM t HAVING id=1″, 就能返回一条记录,而”SELECT * FROM t HAVING id=MAX(id)”本质上是”SELECT * FROM t HAVING id=3″,当然没有返回记录,这就是问题的根源。

测试一下GROUP BY a,这样就对了,每个分组内只有一行,所以MAX/MIN一样大,这回是取得组内最大和最小值。

GROUP BY NULL时MAX/MIN的行为,是这个问题的本质,所以啊,尽量使用标准语法,玩花样SQL之前,一定要搞清楚它的行为是否与理解的一致。

原文发布于微信公众号 - java一日一条(mjx_java)

原文发表时间:2015-06-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏电光石火

SQL 性能调优

我们要做到不但会写SQL,还要做到写出性能优良的SQL,以下为笔者学习、摘录、并汇总部分资料与大家分享! (1)选择最有效率的表名顺序(只在基于规则的优...

31760
来自专栏数据和云

Thinking in SQL系列之数据挖掘C4.5决策树算法

作者简介:牛超 ? 10多年数据库技术积累,长期从事ORACLE数据库管理与开发工作。精通企业级数据库应用设计、SQL、算法实现、异常分析、性能优化。目前...

43360
来自专栏lgp20151222

索引之单列索引和组合索引

若有组合索引(a,b,c),那么根据最左前缀,数据库成立了三个索引(a)(a,b)(a,b,c),

14630
来自专栏性能与架构

简化 SQL 递归查询

自引用类型的表结构处理起来比较麻烦,比如“分类”表,通常包括自己的ID和父分类ID,当我们要做父分类路径、子分类路径之类的查询时很不方便,例如我们会使用嵌套查询...

18140
来自专栏GopherCoder

2016.05.27

16040
来自专栏数据库

Java SQL语句优化经验

. (1) 选择最有效率的表名顺序(只在基于规则的seo/' target='_blank'>优化器中有效): ORACLE 的解析器按照从右到左的顺序处理FR...

34590
来自专栏CodingToDie

MySQL查询优化

1. 查询优化 1. 查询优化 1.2.1. 使用关联查询优化 1.2.2. 使用范围查询 1.1. 最大值和最小值的优化 1.2. 优化 Limit 分页 ...

37660
来自专栏hbbliyong

Oracle 数据字典(可用它动态获取字段名、长度、类型等)

ORACLE数据字典 表名:USER_TAB_COLUMNS TABLE_NAME                           表、视图或聚簇名 ...

47770
来自专栏沃趣科技

MySQL 8.0 新特性之统计直方图

原文链接:https://mysqlserverteam.com/histogram-statistics-in-mysql/

29340
来自专栏程序生活

MySQL的JOIN用法

数据库中的JOIN称为连接,连接的主要作用是根据两个或多个表中的列之间的关系,获取存在于不同表中的数据。连接分为三类:内连接、外连接、全连接。另外还有CROSS...

81620

扫码关注云+社区

领取腾讯云代金券