SQL - DQL(数据查询语言)
DQL(Data Query Language)用来查询数据库表中的记录,查询关键字是 SELECT。 涵盖:基本查询、条件查询、聚合函数、分组查询、排序查询、分页查询。
一、完整语法与执行顺序
SELECT
字段列表
FROM
表名列表
WHERE
条件列表
GROUP BY
分组字段列表
HAVING
分组后条件列表
ORDER BY
排序字段列表
LIMIT
分页参数;
执行顺序(与书写顺序不同):FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
二、基本查询
-- 查询多个字段
SELECT 字段1, 字段2, ... FROM 表名;
SELECT * FROM 表名;
-- 设置别名(AS 可省略)
SELECT 字段1 [AS 别名1], 字段2 [AS 别名2] FROM 表名;
-- 去除重复记录
SELECT DISTINCT 字段列表 FROM 表名;
SELECT name, workno, age FROM emp;
SELECT * FROM emp;
SELECT workaddress AS '工作地址' FROM emp;
SELECT workaddress '工作地址' FROM emp; -- AS 可省略
SELECT DISTINCT workaddress '工作地址' FROM emp; -- 去重
三、条件查询
SELECT 字段列表 FROM 表名 WHERE 条件列表;
比较运算符
| 运算符 | 功能 |
|---|---|
> >= < <= | 大于 / 大于等于 / 小于 / 小于等于 |
= | 等于 |
<> 或 != | 不等于 |
BETWEEN ... AND ... | 在某个范围之内(含最小、最大值) |
IN(...) | 在 in 之后的列表中的值,多选一 |
LIKE 占位符 | 模糊匹配(_ 匹配单个字符,% 匹配任意个字符) |
IS NULL | 是 NULL |
逻辑运算符
| 运算符 | 功能 |
|---|---|
AND 或 && | 并且(多个条件同时成立) |
OR 或 || | 或者(多个条件任意一个成立) |
NOT 或 ! | 非,不是 |
SELECT * FROM emp WHERE age = 88;
SELECT * FROM emp WHERE age < 20;
SELECT * FROM emp WHERE age <= 20;
SELECT * FROM emp WHERE idcard IS NULL; -- 没有身份证号
SELECT * FROM emp WHERE idcard IS NOT NULL; -- 有身份证号
SELECT * FROM emp WHERE age != 88;
SELECT * FROM emp WHERE age <> 88; -- 同上,两种写法等价
SELECT * FROM emp WHERE age BETWEEN 15 AND 20; -- 15 ~ 20(含两端)
SELECT * FROM emp WHERE age >= 15 && age <= 20; -- 等价写法
SELECT * FROM emp WHERE age < 25 && gender = '女';
SELECT * FROM emp WHERE age IN (18, 20, 40);
SELECT * FROM emp WHERE name LIKE '__'; -- 两个字的姓名
SELECT * FROM emp WHERE idcard LIKE '%X'; -- 身份证最后一位是 X
SELECT * FROM emp WHERE idcard LIKE '_________________X'; -- 前 17 位任意、最后 X
- 判断空值不能写
= NULL,只能用IS NULL/IS NOT NULL;BETWEEN a AND b包含两端;- 字符串与日期值要加引号。
四、聚合函数
将一列数据作为一个整体进行纵向计算。
| 函数 | 功能 |
|---|---|
COUNT | 统计数量 |
MAX | 最大值 |
MIN | 最小值 |
AVG | 平均值 |
SUM | 求和 |
SELECT 聚合函数(字段列表) FROM 表名;
SELECT COUNT(idcard) FROM emp; -- 统计员工数量
SELECT AVG(age) FROM emp; -- 平均年龄
SELECT MAX(age) FROM emp; -- 最大年龄
SELECT MIN(age) FROM emp; -- 最小年龄
SELECT SUM(age) FROM emp WHERE workaddress = '西安'; -- 西安地区员工年龄之和
NULL 值不参与所有聚合函数的运算:
COUNT(*)统计所有行,COUNT(字段)不统计该字段为 NULL 的行。
五、分组查询
SELECT 字段列表 FROM 表名 [WHERE 条件] GROUP BY 分组字段名 [HAVING 分组后过滤条件];
WHERE 与 HAVING 的区别
| WHERE | HAVING | |
|---|---|---|
| 执行时机 | 分组之前过滤,不满足条件的不参与分组 | 分组之后对结果过滤 |
| 判断条件 | 不能对聚合函数判断 | 可以对聚合函数判断 |
- 执行顺序:
WHERE> 聚合函数 >HAVING;- 分组之后,查询的字段一般为聚合函数和分组字段,查其他字段没有意义。
-- 按性别分组,统计男、女员工的数量
SELECT gender, COUNT(*) FROM emp GROUP BY gender;
-- 按性别分组,统计男、女员工的平均年龄
SELECT gender, AVG(age) FROM emp GROUP BY gender;
-- 年龄小于 45 的员工按工作地址分组,取员工数 >= 3 的工作地址
SELECT workaddress, COUNT(*) FROM emp WHERE age < 45 GROUP BY workaddress HAVING COUNT(*) >= 3;
-- HAVING 中也可用聚合结果的别名
SELECT workaddress, COUNT(*) AS address_count FROM emp WHERE age < 45 GROUP BY workaddress HAVING address_count >= 3;
六、排序查询
SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1, 字段2 排序方式2;
ASC:升序(默认值)DESC:降序
- 多字段排序时,前一个字段值相同才会按后一个字段排序;
ORDER BY可以使用字段别名或表别名。
SELECT * FROM emp ORDER BY age ASC;
SELECT * FROM emp ORDER BY age; -- 默认升序
SELECT * FROM emp ORDER BY entrydate DESC; -- 按入职时间降序
SELECT * FROM emp ORDER BY age, entrydate DESC; -- 年龄升序,年龄相同按入职时间降序
-- 表别名 + 字段别名排序
SELECT e.name ename, e.age eage FROM emp e WHERE e.age > 15 ORDER BY eage;
七、分页查询
SELECT 字段列表 FROM 表名 LIMIT 起始索引, 查询记录数;
- 起始索引从 0 开始:
起始索引 = (查询页码 - 1) * 每页显示记录数;- 分页查询是数据库的方言,不同数据库实现不同,MySQL 中是
LIMIT;- 查第一页时起始索引可省略,直接写
LIMIT 10。
SELECT * FROM emp LIMIT 0, 10; -- 第 1 页,每页 10 条
SELECT * FROM emp LIMIT 10; -- 同上,首页可省略起始索引
SELECT * FROM emp LIMIT 10, 10; -- 第 2 页,每页 10 条
八、综合练习
-- 1. 查询年龄为 20、21、22、23 的女性员工信息
SELECT * FROM emp WHERE gender = '女' && age IN (20, 21, 22, 23);
-- 2. 查询性别为男、年龄在 20-40(含)以内、且姓名为三个字的员工
SELECT * FROM emp WHERE gender = '男' && age BETWEEN 20 AND 40 && name LIKE '___';
-- 3. 统计年龄小于 60 的男性员工和女性员工的人数
SELECT gender, COUNT(*) FROM emp WHERE age < 60 GROUP BY gender;
-- 4. 查询年龄小于 35 的员工的姓名和年龄,按年龄升序,年龄相同按入职时间降序
SELECT name, age, entrydate FROM emp WHERE age < 35 ORDER BY age, entrydate DESC;
-- 5. 查询性别为男、年龄 20-40(含)以内的前 5 个员工,按年龄升序,年龄相同按入职时间升序
SELECT * FROM emp WHERE gender = '男' && age BETWEEN 20 AND 40 ORDER BY age, entrydate LIMIT 5;
九、速查总结
-- 单表查询骨架(书写顺序,[] 内为可选)
SELECT [DISTINCT] 字段列表 [AS 别名]
FROM 表名
[WHERE 条件] -- 分组前过滤,不能判断聚合函数
[GROUP BY 分组字段 [HAVING 分组后条件]] -- 分组后过滤,可判断聚合函数
[ORDER BY 字段 [ASC | DESC], ...] -- 默认 ASC,多字段依次生效
[LIMIT 起始索引, 记录数]; -- 起始索引 = (页码 - 1) * 每页记录数
| 环节 | 关键字 | 关键点 |
|---|---|---|
| 基本查询 | SELECT / DISTINCT / AS | 别名 AS 可省略;DISTINCT 去重 |
| 条件过滤 | WHERE | IS NULL、BETWEEN a AND b(含两端)、IN(...)、LIKE(_ 单字符 / % 任意字符) |
| 聚合 | COUNT / MAX / MIN / AVG / SUM | NULL 不参与运算,COUNT(*) 统计所有行 |
| 分组 | GROUP BY / HAVING | WHERE 分组前、HAVING 分组后且可判断聚合函数 |
| 排序 | ORDER BY | 默认 ASC;可用字段别名排序 |
| 分页 | LIMIT | 起始索引从 0 开始,查第一页可省略 |
执行顺序:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
相关
- SQL 语法与分类:书写规范 + DDL / DML / DQL / DCL
- SQL - DDL:建库、建表、改表、删表
- SQL - DML:增删改数据
- MySQL 数据类型:数值 / 字符串 / 日期时间