mysql having in_MySQL中无GROUPBY直接HAVING的问题
本文内容遵从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 id=MIN(id);”
但是只是把MIN换成MAX,这样返回就是空了:
“SELECT * FROM t HAVING id=MAX(id);”
这是为什么呢?
我们先来做个试验,验证这种情况。
这是表结构,初始化两条记录,然后试验:
root@localhost : plx 10:25:10> show create table t2\G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL,
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
root@localhost : plx 10:25:15> select * from t2;
+------+----+
| a | id |
+------+----+
| 1 | 1 |
| 1 | 3 |
+------+----+
rows in set (0.00 sec)
root@localhost : plx 10:25:20> SELECT * FROM t2 HAVING id=MIN(id);
+------+----+
| a | id |
+------+----+
| 1 | 1 |
+------+----+
row in set (0.00 sec)
root@localhost : plx 10:25:30> SELECT * FROM t2 HAVING id=MAX(id);
Empty set (0.00 sec)
初看之下,好像真的是这样哎,怎么会这样呢?
我再试一下,把a字段改一个为10,然后试下a字段:
root@localhost : plx 10:26:58> select * from t2;
+------+----+
| a | id |
+------+----+
| 10 | 1 |
| 1 | 3 |
+------+----+
rows in set (0.00 sec)
root@localhost : plx 10:28:20> SELECT * FROM t2 HAVING a=MAX(a);
+------+----+
| a | id |
+------+----+
| 10 | 1 |
+------+----+
row in set (0.00 sec)
root@localhost : plx 10:28:28> 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 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的值:
root@localhost : plx 10:26:58> select * from t2;
+------+----+
| a | id |
+------+----+
| 10 | 1 |
| 1 | 3 |
+------+----+
rows in set (0.00 sec)
root@localhost : plx 10:27:04> SELECT * FROM t2 GROUP BY NULL;
+------+----+
| a | id |
+------+----+
| 10 | 1 |
+------+----+
row in set (0.00 sec)
root@localhost : 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 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 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中文网
mysql having in_MySQL中无GROUPBY直接HAVING的问题相关推荐
- mysql orderby count_mysql中count(),groupby,orderby使用方法分享
本文主要和大家分享mysql中count(), group by, order by使用方法,mysql中order by 排序查询.asc升序.desc降序,group by 分组查询.having ...
- IDEA连接mysql后,schemas中无表格
IDEA连接mysql后,schemas中无表格 例如: 建议: 可以重启idea试试(记得先Apply,如果还没有)
- mysql有符号和无符号,MySQL中的“无符号”是什么意思以及何时使用它?
MySQL中的"无符号"是一种数据类型.每当我们在任何列中写入无符号表示您不能插入负数时.假设对于很大的数字,您可以使用无符号类型. 无符号整数的最大范围是4294967295.N ...
- MySQL 5.7中的更多改进,包括计算列
让我们继续上一周的内容,讨论MySQL 5.7中的新特性,我们将把注意力集中于新的安全方面的特性.首先,新版本中取消了mysql_old_password这个认证插件.其实这个插件从版本4.x开始就已 ...
- mysql 互斥_MySql中互斥量mutex的实现
数据库中的Mutex量指的是一种用于保护一些临界资源的使用的信号量.当有线程需要使用这些临界资源时,会请求获得mutex量,请求成功的线程进入临界区,而请求失败的线程只能等待它释放这个mutex.互斥 ...
- MySQL存储引擎中MyISAM和InnoDB区别
转载自 MySQL存储引擎中MyISAM和InnoDB区别 MyISAM 和InnoDB 讲解 InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应 ...
- mysql select @x_mysql中select * for update
由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例) ,否则MySQL将会执行Table Lock (将整个资料 ...
- mysql8.0源代码解析_源码解读:MySQL 8.0 InnoDB无锁化设计的日志系统
原标题:源码解读:MySQL 8.0 InnoDB无锁化设计的日志系统 作者介绍 张永翔,现任网易云RDS开发,持续关注MySQL及数据库运维领域,擅长MySQL运维,知乎ID:雁南归. MySQL ...
- Python中的groupby分组
Python中的groupby分组 一.groupby函数 groupby函数功能:对DataFrame进行分组(可单类分组,可多类分组) 需求:按"字段"列对数据data进行分组 ...
最新文章
- 使用PHP CURL的POST数据
- 【深度学习】在PyTorch中构建高效的自定义数据集
- 简述dijkstra算法原理_Dijkstra算法之 Java详解
- Java 数据库进度条_java进度条
- 如何实现rtsp h265 转 rtmp (rtsp hevc 转 rtmp)并转发到CDN或自建服务器
- 语音交互有哪些优势与劣势?
- 常用SQL查询语句整理笔记【持续更新】
- 廖雪峰Python教程梳理
- vue学习之监听浏览器宽度
- C++生成DLL文件并使用
- 转载:全志一些具体工作
- android修改HOLO对话框风格
- windows 7 桌面图标变白板的问题解决方法
- STM32CubeMX安装(全图文安装步骤,一步不落下)
- 有限域(2)——理想和商环
- 团队协作常见问题分析与解决
- 2022年docker面试题大全(持续更新中)
- 关于阿里巴巴开发手册不得使用外键与级联,一切外键概念必须在应用层解决的疑惑
- WMS系统学习之ModernWMS
- Google浏览器主页被搜狗导航劫持解决方法(也适用于火狐浏览器)
热门文章
- php aes 3des区别,AES和3DES之间的区别
- java createstatement,createStatement参数说明
- java net php_Java.netPHP比较 | php外包与php技术服务商
- windows配置samba客户端_怎样设置Samba文件服务器以使用Windows客户端
- 13 - java包装类
- android 跳转动画黑屏,Android8.0 适配解决页面跳转过程出现短暂黑屏的问题
- js 二叉树图形_js数据结构和算法(三)二叉树
- 多媒体计算机技术的主要特点,多媒体技术主要特点?
- 操作失败10秒内未完成启动服务mysql_01-MySQL 命令行-cmd用法-未完成
- python 网页自动化框架_python+selenium自动化框架