数据库教程:MySQL中无GROUP BY情况下直接使用HAVING语句的问题探究分享

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

“SELECT*FROMtHAVINGid=MIN(id);”

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

“SELECT*FROMtHAVINGid=MAX(id);”

  这是为什么呢?

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

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

root@localhost:plx10:25:10>showcreatetablet2G ***************************1.row*************************** Table:t2 CreateTable:CREATETABLE`t2`( `a`int(11)DEFAULTNULL, `id`int(10)unsignedNOTNULLAUTO_INCREMENT, PRIMARYKEY(`id`) )ENGINE=InnoDBAUTO_INCREMENT=5DEFAULTCHARSET=utf8 root@localhost:plx10:25:15>select*fromt2; +------+----+ |a|id| +------+----+ |1|1| |1|3| +------+----+ 2rowsinset(0.00sec) root@localhost:plx10:25:20>SELECT*FROMt2HAVINGid=MIN(id); +------+----+ |a|id| +------+----+ |1|1| +------+----+ 1rowinset(0.00sec) root@localhost:plx10:25:30>SELECT*FROMt2HAVINGid=MAX(id); Emptyset(0.00sec)

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

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

root@localhost:plx10:26:58>select*fromt2; +------+----+ |a|id| +------+----+ |10|1| |1|3| +------+----+ 2rowsinset(0.00sec) root@localhost:plx10:28:20>SELECT*FROMt2HAVINGa=MAX(a); +------+----+ |a|id| +------+----+ |10|1| +------+----+ 1rowinset(0.00sec) root@localhost:plx10:28:28>SELECT*FROMt2HAVINGa=MIN(a); Emptyset(0.00sec)

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

  旁白

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

  但是MySQL会做一个重写,加上一个GROUPBYNULL,”SELECT*FROMtHAVINGid=MIN(id)”会被重写为”SELECT*FROMtGROUPBYNULLHAVINGid=MIN(id)”,这样语法就符合规范了。

  继续……

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

root@localhost:plx10:25:48>SELECT*FROMt2GROUPBYNULL; +------+----+ |a|id| +------+----+ |10|1| +------+----+ 1rowinset(0.00sec)

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

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

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

root@localhost:plx10:26:58>select*fromt2; +------+----+ |a|id| +------+----+ |10|1| |1|3| +------+----+ 2rowsinset(0.00sec) root@localhost:plx10:27:04>SELECT*FROMt2GROUPBYNULL; +------+----+ |a|id| +------+----+ |10|1| +------+----+ 1rowinset(0.00sec) root@localhost:plx10:30:21>SELECTMAX(a),MIN(a),MAX(id),MIN(id)FROMt2GROUPBYNULL; +--------+--------+---------+---------+ |MAX(a)|MIN(a)|MAX(id)|MIN(id)| +--------+--------+---------+---------+ |10|1|3|1| +--------+--------+---------+---------+ 1rowinset(0.00sec)

  是不是发现问题了?

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

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

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

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

root@localhost:plx11:29:49>SELECTMAX(a),MIN(a),MAX(id),MIN(id)FROMt2GROUPBYa; +--------+--------+---------+---------+ |MAX(a)|MIN(a)|MAX(id)|MIN(id)| +--------+--------+---------+---------+ |1|1|3|3| |10|10|5|5| +--------+--------+---------+---------+ 2rowsinset(0.00sec)

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

您可能感兴趣的文章:浅谈mysql数据库中的using的用法Mysql之EXPLAIN显示usingfilesort介绍mysql中groupby与having合用注意事项分享MySql中having字句对组记录进行筛选使用说明Mysql中orderby、groupby、having的区别深入分析mysqlhaving用法解析MySQL无GROUPBY直接HAVING返回空的问题分析mysqlgroupbyhaving实例代码MySQL中USING和HAVING用法实例简析

标签: HAVING IN BY SQL

MySQL中删除重复数据的简单方法

探究MySQL中varchar的定义长度

上述就是数据库技术:MySQL中无GROUP BY情况下直接使用HAVING语句的问题探究分享的全部内容,如果对大家有所用处且需要了解更多关于mysql数据库学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/dtteaching/911473.html

(0)
上一篇 2021年10月25日
下一篇 2021年10月25日

精彩推荐