03. Java 条件查询

1. 前言

在 MySQL 中使用 select 查询语句的时候,一般都会加上 where 语句或者 limit 语句限定查询结果的范围,两种子句都是过滤的作用。另外还有和 group by 语句配合使用的 having 限制条件。区分 where 和 having 语句的作用也是比较基础的题目。

2. where 和 having

面试官提问: 请阐述下在 MySQL 中 where 和 having 关键词有什么区别?

题目解析: 为了更加清楚地阐述两个关键用法的不同,我们还是从实际例子出发。

进入上一节创建的测试数据库:

复制代码
USE mybj_demo;

然后进入测试数据库,创建 user 表:

复制代码
USE `mybj_demo`;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '数据库主键',
  `username` varchar(32) DEFAULT NULL COMMENT '用户名',
  `password` varchar(32) DEFAULT NULL COMMENT '密码',
  `gender` int(2) DEFAULT NULL COMMENT '1:男性,2:女性',
  `age` int(10) DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (id) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

然后再插入一些测试数据:

复制代码
insert into user (username,password,gender,age) values ('小明','123456',1,20); 
insert into user (username,password,gender,age) values ('小红','123457',2,22); 
insert into user (username,password,gender,age) values ('小王','123458',1,24); 
insert into user (username,password,gender,age) values ('小刘','123459',2,26); 

2.1 where 和 having 都能使用的场景

复制代码
select username,password,gender,age from user where age >= 20;
select username,password,gender,age from user having age >= 20;

上述两条 sql 都能执行成功,如果 select 之后的字段包含 having 修饰的字段,这种情况下 where 和 having 是等效的。

2.2 只能用 where,不能用 having 的场景

复制代码
select username,password,gender from user where age >= 20;
select username,password,gender from user having age >= 20;

第一条 sql 执行成功,执行第二条 sql 会报错:ERROR 1054 (42S22): Unknown column 'age' in 'having clause',翻译过来就是 "对于 having 语句,age 字段是未知的"。

having 执行的前置条件是:select xxx,... 筛选出的字段包含 having 修饰的关键词。

两者的执行顺序不同:因为 having 是从前面筛选出来的字段中再进行二次筛选,where 则是针对全表先进行筛选。

2.3 只能用 having,不能用 where 的场景

复制代码
select count(*),gender,avg(age) as avg_age from user group by gender where avg_age > 20;
select count(*),gender,avg(age) as avg_age from user group by gender having avg_age > 20;

我们的目的是 "按照性别进行分组,统计平均年龄大于 20 的人数、性别和平均年龄"。

但是第一条 sql 执行会报错:ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where avg_age > 20' at line 1,即对于 where 语句,全表并没有 avg_age 平均年龄这个字段,所以会搜索失败。

从上述的实验结果总结来看,where 和 having 的核心区别有三点:

① 使用范围的不同:

  • where:能够用于 select、update、delete 语句;
  • having:只能用于 select 查询语句。

② 执行顺序不同:

  • where 修饰的搜索条件是在分组完成之前执行;
  • having 修饰的搜索条件是在分组完成之后执行。如果一条 sql 语句同时包含 where 和 having 关键词,会先执行 where 搜索,再执行 having 搜索条件。

③ 聚合函数的联合使用:

  • where:不能联合聚合函数(sum、avg、count、max、min 这类)使用;
  • having:能够联合聚合函数使用。

3. 小结

本章节介绍了 where 和 having 语句的用法和不同点,候选人在阐述的时候需要抓住最核心的一点,where 语句在聚合之前筛选数据,having 语句在聚合之后对数据进行筛选,作用在 group by 语句之后。

相关推荐
Derek_Smart15 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
NE_STOP16 小时前
MyBatis-mybatis入门与增删改查
java
Lee川17 小时前
从异步迷雾到优雅流程:JavaScript异步编程与内存管理的现代化之旅
javascript·面试
晴殇i19 小时前
揭秘JavaScript中那些“不冒泡”的DOM事件
前端·javascript·面试
孟陬19 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
想用offer打牌19 小时前
一站式了解四种限流算法
java·后端·go
绝无仅有19 小时前
Redis过期删除与内存淘汰策略详解
后端·面试·架构
绝无仅有20 小时前
Redis大Key问题排查与解决方案全解析
后端·面试·架构
华仔啊20 小时前
Java 开发千万别给布尔变量加 is 前缀!很容易背锅
java