mysql面试(2)
MySQL面试考点通关:DQL查询操作全解析
前面我们讲了MySQL的基础概念、DDL和DML操作,今天重点攻克DQL(数据查询语言)——这可是面试中最常考、日常开发中用得最多的部分。无论是简单查询还是复杂的多表关联,掌握这些知识点,就能轻松应对面试官的各种"刁难"。
一、DQL基础:查询语句的"骨架"
DQL的核心就是 SELECT
语句,记住这个固定格式,写查询就不会乱:
select 字段 -- 要显示什么
from 表名 -- 从哪张表查
where 筛选条件 -- 过滤掉不需要的数据
group by 分组字段 -- 按规则分组
having 分组后的筛选条件 -- 对分组结果再过滤
order by 排序字段 -- 结果排序
limit 分页参数 -- 只取部分结果
面试必问:DQL的执行顺序
很多人写查询没问题,但说不出执行顺序,这会让面试官觉得你只是"背语法"。记住这个流程:
from 表名
→ 先确定要查哪张表where 筛选条件
→ 先过滤掉大部分无关数据(缩小范围)group by 分组字段
→ 按规则分组having 分组条件
→ 对分组后的结果再筛选(必须跟group by一起用)select 字段
→ 确定最终要显示的内容order by 排序字段
→ 对结果排序limit 分页参数
→ 截取部分结果(比如只看第1页数据)
二、SELECT子句:决定显示什么内容
这部分是查询的"脸面",决定了最终展示的数据样式,高频考点都在这:
1. 查所有字段:select *
简单直接,但实际开发中不推荐(效率低+字段变动有风险):
select * from emp; -- 查emp表所有字段
2. 别名:让结果更易懂
用 as
(可省略)给字段起别名,中文别名加单引号:
select empno as 员工编号,ename '员工姓名', -- 省略assal*12+comm 年薪 -- 计算结果也能起别名
from emp;
3. 简单计算:直接在查询中处理数据
比如计算年薪(月薪×12+奖金):
select ename, sal*12 + ifnull(comm,0) as 年薪 from emp;
注意:用 ifnull(comm,0)
处理null值(null参与计算结果还是null)
4. 去重:distinct
去掉重复值,比如查有哪些经理(排除重复的mgr):
select distinct mgr from emp where mgr is not null;
三、WHERE子句:精准筛选数据
这是过滤数据的关键,各种条件组合是面试重点:
1. 基础运算符
类型 | 常用符号 | 示例 |
---|---|---|
关系运算符 | >、>=、<、<=、!=、= | where sal > 3000 |
逻辑运算符 | and(且)、or(或)、!(非) | where sal > 3000 and deptno=10 |
模糊查询 | like(%匹配任意字符,_匹配1个字符) | where ename like '%A%' (含A的姓名) |
null值查询 | is null / is not null | where comm is null (没奖金的员工) |
2. 优先级处理:用()包裹整体条件
比如查"没奖金,且(入职早于1984年底或姓名含a)"的员工:
where comm is null and (hiredate < '1984-12-31' or ename like '%a%')
3. 函数在WHERE中的应用(高频考点)
MySQL的函数很多,但面试重点考时间函数和流程函数:
时间函数(必背)
-- 1. 获取当前时间
select curdate(), curtime(), now(); -- 日期、时间、日期+时间-- 2. 计算日期差(DATEDIFF)
select datediff(curdate(), '2004-04-04') as 相差天数;-- 3. 查工作超过15000天的员工(经典面试题)
select * from emp where datediff(curdate(), hiredate) > 15000;-- 4. 日期格式化(DATE_FORMAT)
select date_format(hiredate, '%Y年%m月%d日') as 入职日期 from emp;
流程函数(case when)
类似编程语言的if-else,比如给部门编号转成部门名称:
select ename,case deptno when 10 then '开发部'when 20 then '测试部'when 30 then '运维部'end as 部门名称
from emp;
四、GROUP BY:分组查询(统计分析必备)
分组就是"把相同特征的数据放一起统计",比如"每个部门有多少人":
-- 按部门分组,统计每个部门的人数
select deptno, count(empno) as 人数
from emp
group by deptno; -- 有n个不同的deptno就分n组
常用统计函数(多行函数)
这些函数专门配合分组使用,面试高频考点:
函数 | 作用 | 示例 |
---|---|---|
count(字段) | 统计行数 | count(empno) 员工总数 |
max(字段) | 最大值 | max(sal) 最高工资 |
min(字段) | 最小值 | min(sal) 最低工资 |
avg(字段) | 平均值 | avg(sal) 平均工资 |
sum(字段) | 总和 | sum(sal) 工资总和 |
五、HAVING:分组后的筛选条件
having
和 where
都能筛选,但 having
是针对分组结果的,必须跟 group by
一起用:
-- 查平均工资低于2000的部门(先分组算平均,再筛选)
select deptno, avg(sal) as 平均工资
from emp
group by deptno
having 平均工资 < 2000; -- 这里用别名更简洁
面试题:where和having的区别?
where
在分组前筛选,不能用统计函数(比如where avg(sal)>2000
是错的)having
在分组后筛选,可以用统计函数和别名
六、ORDER BY:让结果有序
查询结果默认无序,用 order by
指定排序规则:
-- 按部门号升序(默认asc),同一部门按经理编号降序
select * from emp
order by deptno asc, mgr desc;
注意:时间字段排序很常用(比如按创建时间倒序查最新数据)
七、多表查询:关联数据怎么查?
实际开发中很少查单表,多表关联是必考点,重点掌握内连接和外连接:
1. 内连接([inner] join … on)
只查两张表中匹配成功的数据(地位平等):
-- 查员工姓名和对应的部门地址(员工表emp关联部门表dept)
select e.ename, d.loc
from emp e
inner join dept d
on e.deptno = d.deptno; -- 关联条件(避免笛卡尔积)
2. 外连接(left/right join … on)
分主次表,主表数据全部显示,次表只显示匹配的:
-- 左外连接:emp是主表,即使没部门的员工也会显示
select e.ename, d.loc
from emp e
left join dept d
on e.deptno = d.deptno;
面试必问:内连接和外连接的区别?
- 内连接:只显示两表匹配的数据(交集)
- 外连接:主表数据全显示,次表匹配不上的用null填充
3. 自连接:自己关联自己
把一张表当两张表用,比如查"员工的经理信息":
-- e1是员工表,e2是经理表(经理也是员工)
select e1.ename as 员工, e2.ename as 经理
from emp e1
left join emp e2
on e1.mgr = e2.empno; -- 员工的mgr等于经理的empno
八、子查询:查询里套查询
子查询就是"用一个查询的结果当另一个查询的条件",分两种:
1. 不相关子查询(子查询可独立执行)
子查询先执行,结果给主查询用:
-- 查所有比"CLARK"工资高的员工(单行子查询)
select * from emp
where sal > (select sal from emp where ename='CLARK');
2. 相关子查询(子查询依赖主查询)
子查询需要主查询的数据才能执行,比如"查工资高于本部门平均工资的员工":
select * from emp e2
where sal > (select avg(sal) from emp e1 where e1.deptno = e2.deptno);
(子查询里的e1.deptno依赖主查询的e2.deptno)
九、总结:DQL面试考什么?
- 执行顺序:from→where→group by→having→select→order by→limit(必背)
- 函数应用:尤其是时间函数(datediff、date_format)和case when
- 分组查询:group by与统计函数的配合,having和where的区别
- 多表关联:内连接和外连接的区别,自连接的应用场景
- 子查询:能看懂并写出简单的相关/不相关子查询
记住这些核心点,再结合实际场景多练(比如"统计每个部门的最高工资和人数"),DQL部分的面试就能应对自如了!下一篇可以讲讲索引和事务这些进阶知识点,一步步成为MySQL高手~