执法局网站建设目的,长清做网站,上海到北京高铁最快2个小时,合浦县建设局网站本文内容遵从CC版权协议, 可以随意转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://www.penglixun.com/tech/database/having_without_groupby_in_mysql.html 今天有同学给我反应#xff0c;有一张表#xff0c;id是主键#xff0c;这样的写法可…本文内容遵从CC版权协议, 可以随意转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://www.penglixun.com/tech/database/having_without_groupby_in_mysql.html 今天有同学给我反应有一张表id是主键这样的写法可以返回一条记本文内容遵从CC版权协议, 可以随意转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://www.penglixun.com/tech/database/having_without_groupby_in_mysql.html今天有同学给我反应有一张表id是主键这样的写法可以返回一条记录“SELECT * FROM t HAVING idMIN(id);”但是只是把MIN换成MAX这样返回就是空了“SELECT * FROM t HAVING idMAX(id);”这是为什么呢我们先来做个试验验证这种情况。这是表结构初始化两条记录然后试验rootlocalhost : plx 10:25:10 show create table t2\G*************************** 1. row ***************************Table: t2Create Table: CREATE TABLE t2 (a int(11) DEFAULT NULL,id int(10) unsigned NOT NULL AUTO_INCREMENT,PRIMARY KEY (id)) ENGINEInnoDB AUTO_INCREMENT5 DEFAULT CHARSETutf8rootlocalhost : plx 10:25:15 select * from t2;----------| a | id |----------| 1 | 1 || 1 | 3 |----------rows in set (0.00 sec)rootlocalhost : plx 10:25:20 SELECT * FROM t2 HAVING idMIN(id);----------| a | id |----------| 1 | 1 |----------row in set (0.00 sec)rootlocalhost : plx 10:25:30 SELECT * FROM t2 HAVING idMAX(id);Empty set (0.00 sec)初看之下好像真的是这样哎怎么会这样呢我再试一下把a字段改一个为10然后试下a字段rootlocalhost : plx 10:26:58 select * from t2;----------| a | id |----------| 10 | 1 || 1 | 3 |----------rows in set (0.00 sec)rootlocalhost : plx 10:28:20 SELECT * FROM t2 HAVING aMAX(a);----------| a | id |----------| 10 | 1 |----------row in set (0.00 sec)rootlocalhost : plx 10:28:28 SELECT * FROM t2 HAVING aMIN(a);Empty set (0.00 sec)我擦这回MAX能返回MIN不能了这又是为啥呢旁白一般来说HAVING子句是配合GROUP BY使用的单独使用HAVING本身是不符合规范的但是MySQL会做一个重写加上一个GROUP BY NULL”SELECT * FROM t HAVING idMIN(id)”会被重写为”SELECT * FROM t GROUP BY NULL HAVING idMIN(id)”这样语法就符合规范了。继续……但是这个 GROUP BY NULL 会产生什么结果呢经过查看代码和试验可以证明GROUP BY NULL 等价于 LIMIT 1rootlocalhost : plx 10:25:48 SELECT * FROM t2 GROUP BY NULL;----------| a | id |----------| 10 | 1 |----------row in set (0.00 sec)也就是说GROUP BY NULL 以后只会有一个分组里面就是第一行数据。但是如果这样MIN、MAX结果应该是一致的那也不应该MAX和MIN一个有结果一个没结果啊这是为什么呢再做一个测试。修改一下数据然后直接查看MIN/MAX的值rootlocalhost : plx 10:26:58 select * from t2;----------| a | id |----------| 10 | 1 || 1 | 3 |----------rows in set (0.00 sec)rootlocalhost : plx 10:27:04 SELECT * FROM t2 GROUP BY NULL;----------| a | id |----------| 10 | 1 |----------row in set (0.00 sec)rootlocalhost : plx 10:30:21 SELECT MAX(a),MIN(a),MAX(id),MIN(id) FROM t2 GROUP BY NULL;----------------------------------| MAX(a) | MIN(a) | MAX(id) | MIN(id) |----------------------------------| 10 | 1 | 3 | 1 |----------------------------------row in set (0.00 sec)是不是发现问题了MAX/MIN函数取值是全局的而不是LIMIT 1这个分组内的。因此当GROUP BY NULL的时候MAX/MIN函数是取所有数据里的最大和最小值所以啊”SELECT * FROM t HAVING idMIN(id)”本质上是”SELECT * FROM t HAVING id1″, 就能返回一条记录而”SELECT * FROM t HAVING idMAX(id)”本质上是”SELECT * FROM t HAVING id3″当然没有返回记录这就是问题的根源。测试一下GROUP BY a这样就对了每个分组内只有一行所以MAX/MIN一样大这回是取得组内最大和最小值。rootlocalhost : plx 11:29:49 SELECT MAX(a),MIN(a),MAX(id),MIN(id) FROM t2 GROUP BY a;----------------------------------| MAX(a) | MIN(a) | MAX(id) | MIN(id) |----------------------------------| 1 | 1 | 3 | 3 || 10 | 10 | 5 | 5 |----------------------------------rows in set (0.00 sec)GROUP BY NULL时MAX/MIN的行为是这个问题的本质所以啊尽量使用标准语法玩花样SQL之前一定要搞清楚它的行为是否与理解的一致。Enjoy MySQL!本条技术文章来源于互联网如果无意侵犯您的权益请点击此处反馈版权投诉本文系统来源php中文网