WHERE关键字
WHERE的作用
text
复制代码
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
sql
复制代码
SELECT *
FROM employee
WHERE salary > 5000;
- 含义:先从表中筛选出 salary > 5000 的记录,再返回结果。
HAVING 关键字
HAVING 的作用
- HAVING 是在分组之后对聚合结果进行过滤。
- 示例:
sql
复制代码
SELECT dept, COUNT(*)
FROM employee
GROUP BY dept
HAVING COUNT(*) > 2;
执行逻辑:先按 dept 分组,计算每组 COUNT(*),再过滤 COUNT(*) > 2
WHERE 和 HAVING 的区别
- WHERE 和 HAVING 都是 SQL 中的过滤条件,但它们的作用阶段不同。
| 区别 |
WHERE |
HAVING |
| 作用阶段 |
分组前过滤 |
分组后过滤 |
| 是否可以使用聚合函数 |
不可以 |
可以 |
| 是否必须配合 GROUP BY |
不需要 |
一般需要 |
为什么 HAVING 需要和 GROUP BY 使用
- 因为 HAVING 的作用是过滤聚合结果,而聚合结果只有在分组之后才会产生。
- 常见的聚合函数:
sql
复制代码
count(*) sum() max() min() AVG()
text
复制代码
1 FROM 找到表
2 WHERE 过滤行数据
3 GROUP BY 分组
4 聚合函数计算
5 HAVING 过滤分组结果
6 SELECT
7 ORDER BY
- 因此 WHERE 过滤原始数据,HAVING 过滤聚合后的数据
什么时候用 WHERE,什么时候用 HAVING
- 原则:能用 WHERE 就不要用 HAVING。
- 原因:WHERE 在分组前过滤,数据量更少,效率更高。
- 举例:
sql
复制代码
SELECT dept, COUNT(*)
FROM employee
WHERE salary > 5000
GROUP BY dept
HAVING COUNT(*) > 2;
- WHERE 先过滤工资 > 5000 的员工
- GROUP BY 再分组
- HAVING 再过滤部门人数
MySQL 的索引
- 索引是 MySQL 中提升查询效率的核心工具,可以把它理解成书籍的目录------ 没有目录时找内容要逐页翻(全表扫描),有目录时能直接定位到目标页码(快速查询)。
索引的核心作用
- 加速查询:这是最核心的作用,避免全表扫描,直接定位符合条件的数据。
- 优化排序/分组:对需要 ORDER BY/GROUP BY 的字段建索引,可避免临时表排序,提升效率。
- 唯一约束:如主键索引、唯一索引,能保证字段值的唯一性(比如用户手机号不能重复)。
- 注意:索引会降低插入/更新/删除的效率(因为修改数据时要同步维护索引),所以不是索引越多越好,按需创建即可。
索引的分类
- 功能分类:主键索引、唯一索引、全文索引、普通索引
- 数据结构分类:b+树索引、哈希索引
- 存储位置分类:聚簇索引、非聚簇索引
| 索引类型 |
特点 |
适用场景 |
| 主键索引(PRIMARY KEY) |
唯一、非空,一张表只能有 1 个主键索引 |
表的唯一标识(如用户 ID) |
| 唯一索引(UNIQUE) |
唯一,但允许 NULL(多个 NULL 不冲突),一张表可创建多个 |
唯一标识字段(如手机号、邮箱) |
| 普通索引(INDEX) |
无唯一性约束,最常用 |
普通查询字段(如商品名称、分类) |
| 组合索引(复合索引) |
基于多个字段的索引,遵循最左前缀原则 |
多字段联合查询(如 WHERE 分类=1 AND 价格<100) |
| 全文索引(FULLTEXT) |
针对文本内容的模糊匹配优化(如文章内容搜索),仅支持 MyISAM/InnoDB(5.6+),适用于 CHAR、VARCHAR 和 TEXT 等字段。 |
长文本模糊查询(如 MATCH(content) AGAINST('关键词')) |
- 主键索引=唯一索引+非空。每个表只能有一个主键索引,但可以有多个唯一索引。
- 普通索引仅用于加速查询,不限制字段值的唯一性;适用于高频写入的字段、范围查询的字段。
- 唯一索引强制字段值的唯一性,插入或更新时会触发唯一性检查;适用于业务唯一性约束的字段、防止数据重复插入的字段。
索引的底层结构
- MySQL 中绝大多数索引(主键、唯一、普通、组合)的底层是B+树
- B+ 树特点:
- 所有数据都存在叶子节点,且叶子节点按顺序连成链表(方便范围查询,如 WHERE id BETWEEN 10 AND 20);
- 非叶子节点只存索引值,不存数据,能让索引树更"矮胖",减少磁盘 IO 次数。
- 对比哈希索引:
- 哈希索引(Memory 引擎支持)查询等值快,但不支持范围查询、排序,而B+树索引完全支持。
常见的索引失效场景
- 违反最左前缀原则:组合索引 (a,b,c),查询时只用 b/c、或 b,c,索引失效(必须从最左的 a 开始用)。
- 字段做函数/运算:如 WHERE SUBSTR(phone,1,3)='138'、WHERE id+1=10,索引失效。
- 使用模糊查询前缀 %:WHERE name LIKE '%张三' 失效,WHERE name LIKE '张三%' 有效。
- 字段类型不匹配:如 phone 是 VARCHAR 类型,查询时写 WHERE phone=13800138000(数字),索引失效。
- 使用OR连接非索引字段:如 WHERE name='张三' OR age=20(age 无索引),索引失效。