Day4学习--MySQL高级
分页查询
-
limit关键字
-
起始索引从0开始
-
分页查询是数据库的方言,不同的数据库有不同的实现,MySQL中是limit
-
如果起始索引为0,起始索引可以省略,直接简写为limit 10
sql
-- =================== 分页查询 ======================
-- 1. 从起始索引0开始查询员工数据, 每页展示5条记录
select * from emp limit 5;
-- 2. 查询 第1页 员工数据, 每页展示5条记录
select * from emp limit 0, 5;
-- 3. 查询 第2页 员工数据, 每页展示5条记录
select * from emp limit 5, 5;
-- 4. 查询 第3页 员工数据, 每页展示5条记录
select * from emp limit 10, 5;
-- 页码
-- 起始索引 = 页码 - 1 * 每页展示记录数
聚合函数与分组查询
- 聚合函数:将一列数据作为一个整体,进行纵向计算。
sql
-- =================== DQL: 分组查询 ======================
-- 聚合函数
-- 注意:所有的聚合函数不参与null值统计
-- 1. 统计该企业员工数量
-- count(字段):最后考虑
select count(job) from emp;
-- count(*):优先推荐
select count(*) from emp;
-- count(常量):推荐
select count(1) from emp;
-- 2. 统计该企业员工的平均薪资
select avg(salary) from emp;
-- 3. 统计该企业员工的最低薪资
select min(salary) from emp;
-- 4. 统计该企业员工的最高薪资
select max(salary) from emp;
-- 5. 统计该企业每月要给员工发放的薪资总额(薪资之和)
select sum(salary) from emp;
-
where与having的区别:
-
执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组之后对结果进行过滤。
-
判断条件不同:where不能对聚合函数进行判断,而having可以。
-
sql
-- 分组
-- 分组之后,select后的字段列表不能随意书写,能写的一般是分组字段和聚合函数
-- 1. 根据性别分组 , 统计男性和女性员工的数量
select gender, count(*) from emp group by gender;
-- 2. 先查询入职时间在 '2015-01-01' (包含) 以前的员工 , 并对结果根据职位分组 , 获取员工数量大于等于2的职位
select job,count(*) from emp where entry_date <= '2015-01-01' group by job having count(*) >= 2;
业务表设计
- 我模拟了企业中常见的"部门-员工"一对多关系,设计原则强调"外键关联"与"范式规范"。部门表
t_dept作为主表,包含id和dept_name;员工表t_emp作为从表,通过dept_id字段关联部门表的主键。这种设计不仅消除了数据冗余,还通过外键约束保证了数据的完整性。
sql
-- 部门表(主表)
CREATE TABLE t_dept (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '部门ID',
dept_name VARCHAR(50) NOT NULL COMMENT '部门名称'
) COMMENT '部门表';
-- 员工表(从表,通过dept_id建立一对多关系)
CREATE TABLE t_emp (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '员工ID',
emp_name VARCHAR(50) NOT NULL COMMENT '姓名',
age INT COMMENT '年龄',
salary DECIMAL(10, 2) COMMENT '薪资',
dept_id INT COMMENT '所属部门ID',
FOREIGN KEY (dept_id) REFERENCES t_dept(id) ON DELETE SET NULL
) COMMENT '员工表';
-- 避坑指南:排序字段若为字符串,需转换为数值类型,否则"100"会排在"20"前面
SELECT id, emp_name, age_str FROM t_emp ORDER BY CAST(age_str AS UNSIGNED) DESC;
-- 聚合分组实战:统计每个部门的平均薪资,且只保留平均薪资高于8000的部门
SELECT
d.dept_name,
COUNT(e.id) AS emp_count,
AVG(e.salary) AS avg_salary
FROM t_emp e
JOIN t_dept d ON e.dept_id = d.id
GROUP BY d.dept_name
HAVING AVG(e.salary) > 8000;
索引
- 索引相当于数据库表的目录,可以大幅提升查询的速度,减少全表的扫描,优化查询性能
sql
-- 1. 创建普通索引
CREATE INDEX idx_emp_deptid ON t_emp(dept_id);
-- 2. 创建唯一索引
CREATE UNIQUE INDEX idx_dept_name ON t_dept(dept_name);
-- 3. 查看表索引
SHOW INDEX FROM t_emp;
-- 4. 删除索引
DROP INDEX idx_emp_deptid ON t_emp;
联表查询和索引优化实战案例
sql
-- 左连接实战:查询所有部门及员工信息,无员工的部门也要显示
SELECT
d.dept_name,
e.emp_name,
e.salary
FROM t_dept d
LEFT JOIN t_emp e ON d.id = e.dept_id;
-- 索引创建与验证
-- 创建覆盖索引,优化按用户统计订单金额的查询
CREATE INDEX idx_user_amount ON orders(user_id, amount);
-- 使用EXPLAIN分析执行计划,观察key_len是否命中联合索引
EXPLAIN SELECT * FROM t_emp WHERE emp_name = '张三' AND age = 25;
-- 输出中 key_len 应包含 name 和 age 两部分的长度,表示索引全部生效
-- 批量操作优化:避免在代码中循环单条插入,使用批量INSERT减少网络交互
INSERT INTO t_emp (emp_name, dept_id, salary) VALUES
('李四', 1, 9000.00),
('王五', 2, 8500.00),
('赵六', 1, 9200.00);
SQL优化基础
查询优化
- 避免使用**SELECT * **,按需查询所需字段,减少数据的传输
- 如果分页时要求的数据量比较大,建议使用主键id去优化,避免偏移量过大造成性能损失
- 避免在索引列上进行函数运算或类型转换(如
WHERE YEAR(create_time) = 2026会导致索引失效,应改为范围查询) - 在多表查询时,务必先在
WHERE子句中对大表进行条件筛选,缩小数据集后再进行JOIN操作,避免将大量无用数据卷入关联计算
联表和分组查询优化
- 联表查询优先使用主键或索引
- 在进行
JOIN操作时,应确保数据量小的表作为驱动表(写在JOIN左侧或FROM后),数据量大的表作为被驱动表。这样能减少外层循环的次数,降低匹配开销。其次是"先过滤再关联"。
模糊查询优化
- 模糊查询
LIKE的前缀不能为%(如LIKE '%张'无法走索引)
深分页场景
- 坚决摒弃大偏移量的
LIMIT,转而使用主键游标法