本文来自网址: 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. TableView的执行流程 & 位移枚举

    // 闲来无聊测试一下 第一轮: 1.numberOfSectionsInTableView    :假如section=2,此函数只执行一次,假如section=0,下面函数不执行,默认为1 2.h ...

  2. linux下vim更改注释颜色

    我linux下默认底色是黑色,字体是绿色,但是注释默认是蓝色,,很不爽...所以要更改注释颜色......以下文章来自转载. from: http://blog.csdn.net/gz109/arti ...

  3. 利用Node.js对某智能家居服务器重构

    原文摘自我的前端博客,欢迎大家来访问 http://www.hacke2.cn 之前负责过一个智能家居项目的开发,外包重庆一家公司的,我们主要开发服务器监控和集群版管理. 移动端和机顶盒的远程通信是用 ...

  4. 清北学堂模拟day4 传球接力

    [问题描述]n 个小朋友在玩传球. 小朋友们用 1 到 n 的正整数编号. 每个小朋友有一个固定的传球对象,第 i 个小朋友在接到球后会将球传给第 ai个小朋友, 并且第 i 个小朋友与第 ai个小朋 ...

  5. IBM:领导力素质的三环模式

    文章来源:http://blog.vsharing.com/sdtcj/A1826934.html   在翰威特公司于2003年评选的美国企业“领导人才最佳雇主”名单上,IBM名列榜首.而纽约< ...

  6. 第2月第3天 egorefresh

    egorefresh是很老的下拉刷新,它是一个uiview,在uitableview 下拉的时候显示不同的界面. egorefresh和uitableview的耦合度很高,uitableview滚动和 ...

  7. lua操作json,mysql,redis等

    ==========================example for lua json======================= local cjson = require("cj ...

  8. JS的构造函数

    //构造函数  //使自己的对象多次复制,同时实例根据设置的访问等级可以访问其内部的属性和方法  //当对象被实例化后,构造函数会立即执行它所包含的任何代码  function myObject(ms ...

  9. linux C之getchar()非阻塞方式

    参考链接: http://blog.csdn.net/zydlyq/article/details/50963360 #include "../include/CommUart.h" ...

  10. html5 图片转为base64格式异步上传

    因为有这个需求(移动端),所以就研究了一下,发现还挺不错的.这个主要是用了html5的API,不需要其他的JS插件,不过只有支持html5的浏览器才行,就现在而言应该大部份都支持的.<!DOCT ...