本文来自网址: http://www.penglixun.com/tech/database/having_without_groupby_in_mysql.html

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

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

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

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

这是为什么呢?

我们先来做个试验,验证这种情况。
这是表结构,初始化两条记录,然后试验:

root@localhost : plx ::> show create table t2\G
*************************** . row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`a` int() DEFAULT NULL,
`id` int() unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8
 
root@localhost : plx ::> select * from t2;
+------+----+
| a | id |
+------+----+
| | |
| | |
+------+----+
rows in set (0.00 sec)
 
root@localhost : plx ::> SELECT * FROM t2 HAVING id=MIN(id);
+------+----+
| a | id |
+------+----+
| | |
+------+----+
row in set (0.00 sec)
 
root@localhost : plx ::> SELECT * FROM t2 HAVING id=MAX(id);
Empty set (0.00 sec)

初看之下,好像真的是这样哎,怎么会这样呢?我再试一下,把a字段改一个为10,然后试下a字段:

root@localhost : plx ::> select * from t2;
+------+----+
| a | id |
+------+----+
| | |
| | |
+------+----+
rows in set (0.00 sec)
 
root@localhost : plx ::> SELECT * FROM t2 HAVING a=MAX(a);
+------+----+
| a | id |
+------+----+
| | |
+------+----+
row in set (0.00 sec)
 
root@localhost : plx ::> SELECT * FROM t2 HAVING a=MIN(a);
Empty set (0.00 sec)

我擦,这回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

root@localhost : plx ::> SELECT * FROM t2 GROUP BY NULL;
+------+----+
| a | id |
+------+----+
| | |
+------+----+
row in set (0.00 sec)

也就是说,GROUP BY NULL 以后,只会有一个分组,里面就是第一行数据。
但是如果这样,MIN、MAX结果应该是一致的,那也不应该MAX和MIN一个有结果,一个没结果啊,这是为什么呢,再做一个测试。
修改一下数据,然后直接查看MIN/MAX的值:

root@localhost : plx ::> select * from t2;
+------+----+
| a | id |
+------+----+
| | |
| | |
+------+----+
rows in set (0.00 sec)
 
root@localhost : plx ::04> SELECT * FROM t2 GROUP BY NULL;
+------+----+
| a | id |
+------+----+
| | |
+------+----+
row in set (0.00 sec)
 
root@localhost : plx ::> SELECT MAX(a),MIN(a),MAX(id),MIN(id) FROM t2 GROUP BY NULL;
+--------+--------+---------+---------+
| MAX(a) | MIN(a) | MAX(id) | MIN(id) |
+--------+--------+---------+---------+
| | | | |
+--------+--------+---------+---------+
row in set (0.00 sec)

是不是发现问题了?
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一样大,这回是取得组内最大和最小值。

root@localhost : plx ::> SELECT MAX(a),MIN(a),MAX(id),MIN(id) FROM t2 GROUP BY a;
+--------+--------+---------+---------+
| MAX(a) | MIN(a) | MAX(id) | MIN(id) |
+--------+--------+---------+---------+
| | | | |
| | | | |
+--------+--------+---------+---------+
rows in set (0.00 sec)

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

MySQL中无GROUP BY直接HAVING的问题【转】的更多相关文章

  1. 在mysql中使用group by和order by取每个分组中日期最大一行数据

    转载自:https://blog.csdn.net/shiyong1949/article/details/78482737 在mysql中使用group by进行分组后取某一列的最大值,我们可以直接 ...

  2. MySQL中使用group by 是总是出现1055的错误

    因为在MySQL中使用group by 是总是出现1055的错误,这就导致了必须去查看是什么原因了,查询了相关的资料,现在将笔记记录下来,以便后面可以参考使用: sql_mode:简而言之就是:它定义 ...

  3. mysql中count(),group by使用

    count()统计表中或数组中记录 count(*)返回检索行的数目,且不论其值中是否包含NULL count(column_name)返回的是对列中column_name不为NULL的行的统计 例如 ...

  4. mysql中利用group by过滤删除重复行

    DELETEFROM peopleWHERE peopleId IN (SELECT peopleId FROM people GROUP BY peopleId HAVING count(peopl ...

  5. MySql中对Group by后的结果数进行Count

    今天在写MySQ的SQL语句的时候遇到了一个奇怪的问题 select count(*) from subsitealbum t1, photo t2,files t3 where t1.SourceA ...

  6. MYSQL中GROUP BY不包含所有的非聚合字段时的注意事项

    本文导读:在MYSQL中使用GROUP BY分组时,我们可以select 多个非聚合字段,但是这些字段不在GROUP BY中,这样的SQL查询在SQL SERVER.ORACLE中是不合理的,且会报错 ...

  7. GROUP BY和HAVING 以及mysql中常用的日期函数

    一.mysql中的GROUP BY和HAVINGGROUP BY常见的是和聚合函数(SUM,MIN,MAX,COUNT)搭配使用. 比如:SELECT category,SUM(money) AS ` ...

  8. MySQL中数组的存储

    1. MySQL中以字符串的形式存储数组 MySQL中无数组类型,通常将数组元素按某个字符分割以字符串形式存储 1.1. 求数组中元素的个数 方法:按指定符号分割字符串,返回分割后的元素个数.方法很简 ...

  9. mysql中相关,无关子查询,表与表之间的关系以及编码和乱码的解决

    ※MySQL中的字符编码(注意,utf8中没有'-',跟Java中不一样)SHOW VARIABLES; //查看系统变量//查询字符编码相关的系统变量SHOW VARIABLES WHERE var ...

随机推荐

  1. 关于IOC的思考

    SOLID面向对象的五个设计原则对于开发人员非常重要,其身影在任何大中型软件项目中随处可见,建议必须掌握并灵活应用.此五原则分别为:     单一职责原则(Single Resposibility P ...

  2. 关于shell脚本时遇value too great for base (error token is "08")

    今天在书写一个定时cp脚本时遇到了一个问题,value too great for base (error token is "08") 在网上查看到原来是以0开头的数字 系统会默 ...

  3. ASP.NET MVC 4 的JS/CSS打包压缩功能-------过滤文件

    今天在使用MVC4打包压缩功能@Scripts.Render("~/bundles/jquery") 的时候产生了一些疑惑,问什么在App_Start文件夹下BundleConfi ...

  4. NetBeans使用习惯:升级与保存配置

    如何升级:点击 netbeans 的升级更新 ,即可升级版本:不推荐官网下载进行安装,否则会出现,以前的旧版本8.0的目录和8.0.1目录,虽然它会自动检测到以前版本的配置,提示导入... 如何备份: ...

  5. OC第八节——目录操作和文件管理

    1.需要理解的知识            通常程序在运行中或者程序结束之后,需要保存一些信息,而且需要持久化存储信息,比如登陆信息.视频播放记录.收藏记录等等,那么我们可以采用以下几种方式对数据进行持 ...

  6. LUXURY 8

    A - Gargari and Bishops Time Limit:3000MS     Memory Limit:262144KB     64bit IO Format:%I64d & ...

  7. Android手机如何通过USB共享网络给Mac?

    最近网络挂了,mac不能上网查资料,心情非常毛躁,急切寻求用mac蹭WiFi的方法. 没有找到电脑端破解WiFi密码的软件,手头的Android手机没有root,也无法查看WiFi密码--->破 ...

  8. HPC Linux

    HPC也就是高性能计算,网格计算.服务器集群等前些日子听了Dr. Allen D. Malony讲座结束时得到两张光盘:一个HPC Linux的live cd,一个virtual box的ova镜像文 ...

  9. iOS企业级开发初级课程-表视图(13集)

    首先了解了表视图的组成.表视图类的构成.表视图的分类以及表视图的两个重要协议(委托协议和数据源协议),对表视图有了一个整体上的认识.接下来我们掌握了如何实现简单表视图和分节表视图,以及表视图中索引.搜 ...

  10. iOS开发——常见错误——使用MJRefresh返回上一个界面蹦掉的情况

    最近在使用MJRefresh框架时发现了一个bug 下面是我的源代码 前一个界面 -(void)tableView:(UITableView *)tableView didSelectRowAtInd ...