SQL DQL数据查询语言全套学习笔记(基础查询→执行顺序全解析)

前言

在关系型数据库(MySQL 为主)开发工作里,DQL(Data Query Language,数据查询语言)是 SQL 使用频次最高的语法子集,核心关键字为SELECT,业务数据筛选、报表统计、前端接口数据读取全都依赖 DQL 完成。本文顺着课程章节:基础查询、条件查询、聚合函数、分组查询、排序查询、分页查询、实战案例、SQL 执行顺序、知识点总结,系统拆解 DQL 用法,附带可直接复刻的 SQL 示例、易错避坑点,适配后端入门学习者做技术博客沉淀、面试复习。

一、15 节:DQL 基础查询(SELECT 基础语法)

1. 标准基础语法格式

复制代码
-- 查询指定单列/多列
SELECT 列名1,列名2 FROM 表名;
-- 查询整张表所有字段(生产环境禁止滥用*,会触发不必要的全字段IO)
SELECT * FROM 表名;
-- 字段起别名,AS关键字可省略
SELECT 字段 AS 别名, 字段2 别名2 FROM 表名;
-- 去重查询DISTINCT
SELECT DISTINCT 字段 FROM 表名;
-- 字段做运算(数值列支持加减乘除)
SELECT 字段+10 FROM 表名;

2. 实操样例(以员工表 emp 为例)

复制代码
-- 1.查询员工姓名、薪资两列
SELECT name,salary FROM emp;
-- 2.给薪资列起别名month_salary
SELECT name,salary AS month_salary FROM emp;
-- 3.去重查询员工所属部门编号
SELECT DISTINCT dept_id FROM emp;
-- 4.计算员工年薪(月薪*12)
SELECT name,salary*12 annual_salary FROM emp;

3. 避坑提醒

  1. SELECT *在大表场景性能很差,索引无法精准命中,线上业务务必枚举需要的字段;

  2. DISTINCT 对多列生效时,会按照多列组合值整体去重,不是单独针对首个字段;

  3. NULL 参与算术运算,运算结果永远为 NULL,不能直接靠加减处理空薪资字段。

二、16 节:DQL 条件查询(WHERE 子句过滤行数据)

1. 语法结构

复制代码
SELECT 字段列表 FROM 表名 WHERE 筛选条件;

WHERE 执行时机:FROM 加载数据表数据后,逐行校验条件,只把符合规则的行向下传递给后续逻辑。

2. 常用条件运算符分类

  1. 基础比较运算符:>、<、>=、<=、=、!= / <>(两个写法都代表不等于)

  2. 范围匹配:BETWEEN 最小值 AND 最大值(闭区间,包含两端边界)、IN(值1,值2)匹配离散枚举值

  3. 空值判定:IS NULLIS NOT NULL(禁止用=NULL做空值匹配,SQL 中 NULL 不等于自身)

  4. 模糊匹配LIKE%匹配任意长度任意字符、_匹配单个任意字符

  5. 逻辑运算符:AND(且)OR(或)NOT(取反),优先级:AND > OR

3. 代码示例

复制代码
-- 1.查询薪资大于8000的员工
SELECT name,salary FROM emp WHERE salary>8000;
-- 2.薪资区间5000~10000的员工(两种等价写法)
SELECT name FROM emp WHERE salary BETWEEN 5000 AND 10000;
SELECT name FROM emp WHERE salary>=5000 AND salary<=10000;
-- 3.部门编号为1、3的员工
SELECT name FROM emp WHERE dept_id IN(1,3);
-- 4.查询姓名姓张的员工模糊匹配
SELECT name FROM emp WHERE name LIKE '张%';
-- 5.查询薪资不为空的员工
SELECT name FROM emp WHERE salary IS NOT NULL;

易错点

OR 和 AND 混用不加括号会出现逻辑偏差,例:想筛选「薪资 > 10000 或者 部门 id=2 且薪资 > 6000」,必须书写salary>10000 OR (dept_id=2 AND salary>6000)

三、17 节:DQL 聚合函数(纵向整列做统计计算)

1. 核心概念

普通 WHERE 做横向单行数据筛选 ,聚合函数对指定列做纵向全行汇总统计,MySQL 内置通用聚合函数:

|---------------|--------|-----------------------------------------|
| 函数 | 功能说明 | NULL 处理规则 |
| COUNT (列 /*) | 统计数据行数 | COUNT (*) 统计所有行;COUNT (字段) 自动跳过 NULL 行 |
| SUM (列) | 列的数值求和 | 忽略 NULL |
| AVG (列) | 列平均值 | 忽略 NULL |
| MAX (列) | 取列最大值 | 忽略 NULL |
| MIN (列) | 取列最小值 | 忽略 NULL |

2. 示例 SQL

复制代码
-- 员工总人数
SELECT COUNT(*) total_emp FROM emp;
-- 全体员工薪资总和、平均薪资
SELECT SUM(salary) sum_sal,AVG(salary) avg_sal FROM emp;
-- 最高、最低月薪
SELECT MAX(salary) max_sal,MIN(salary) min_sal FROM emp;

关键避坑

AVG 函数跳过 NULL 行,若岗位空缺薪资为 NULL,空缺记录不会纳入平均值分母统计,业务要补默认值再做统计;WHERE 子句内不能直接书写聚合函数,聚合过滤要放到 HAVING 子句。

四、18 节:DQL 分组查询(GROUP BY 分组 + having 分组后过滤)

1. 标准语法

复制代码
SELECT 分组字段,聚合函数 FROM 表名
WHERE 分组前置行过滤
GROUP BY 分组字段
HAVING 分组结果二次过滤;

WHERE:分组前筛选原始单行数据,不能引用聚合函数;HAVING:分组完成后对每组统计结果过滤,支持书写聚合函数。

2. 实操案例:按部门分组统计部门平均薪资,筛选部门平均薪资大于 7000 的分组

复制代码
SELECT dept_id,AVG(salary) dept_avg_sal
FROM emp
WHERE salary>3000 -- 先剔除底薪过低无效数据,减少分组计算量
GROUP BY dept_id
HAVING AVG(salary) > 7000;

硬性规范(MySQL 开发强制约束)

SELECT 后非聚合的普通字段,必须出现在 GROUP BY 分组字段列表内,禁止查询分组外零散字段(MySQL 宽松模式会产出逻辑错乱数据)。

五、19 节:DQL 排序查询(ORDER BY 对结果集排序)

1. 语法规则

复制代码
SELECT 字段 FROM 表名 [WHERE过滤] [GROUP BY分组]
ORDER BY 排序字段1 排序方式,排序字段2 排序方式;

排序标识:ASC升序(默认可省略)、DESC降序;支持多字段排序:优先按首个字段排序,首个字段数值相同时,启用第二个字段补充排序。

示例 SQL

复制代码
-- 员工薪资降序排列
SELECT name,salary FROM emp ORDER BY salary DESC;
-- 部门编号升序,同部门内薪资由高到低排序
SELECT dept_id,name,salary FROM emp ORDER BY dept_id ASC,salary DESC;

补充特性

NULL 值在升序排序场景,MySQL 会把 NULL 行排在结果集最顶部;排序字段建议建立索引,大数据量表排序避免触发 filesort 文件磁盘排序拖垮性能。

六、20 节:DQL 分页查询(LIMIT 实现数据分页)

1.MySQL 专属分页语法

复制代码
SELECT 字段 FROM 表名 前置过滤逻辑 ORDER BY 排序列
LIMIT 起始偏移量offset,单页展示条数page_size;

分页计算公式:offset = (页码-1)*每页条数;LIMIT 仅 MySQL、MariaDB 支持,Oracle 使用 ROWNUM、SQL Server 使用 OFFSET FETCH 做分页。

业务示例:每页 10 条,查询第 3 页数据

复制代码
-- offset=(3-1)*10=20
SELECT * FROM emp ORDER BY emp_id LIMIT 20,10;
-- MySQL8.0可读更强的写法
SELECT * FROM emp ORDER BY emp_id LIMIT 10 OFFSET 20;

性能优化要点

深分页(offset 数值上万)性能会急剧衰减,优化方案:主键索引分页、子查询先定位主键再回表查询;分页必须搭配稳定排序字段(主键 ID),避免分页出现数据重复、漏取。

七、21 节:DQL 综合案例练习(整合多类子句)

业务需求背景

员工表 emp 字段:emp_id (主键),name,salary,dept_id,entry_date 入职时间,完成 3 个综合需求:

  1. 统计 2024 年入职员工,分部门统计部门员工人数,只保留部门人数≥2 的分组;按人数降序分页,取前 5 条结果

    SELECT dept_id,COUNT(emp_id) emp_cnt
    FROM emp
    WHERE entry_date >= '2024-01-01' AND entry_date < '2025-01-01'
    GROUP BY dept_id
    HAVING COUNT(emp_id)>=2
    ORDER BY emp_cnt DESC
    LIMIT 5;

  2. 模糊筛选姓名带 "李" 字、月薪 6k~15k 的员工,薪资倒序展示

    SELECT name,salary FROM emp
    WHERE name LIKE '%李%' AND salary BETWEEN 6000 AND 15000
    ORDER BY salary DESC;

  3. 排查部门内最高薪资低于 5000 的低效部门编号

    SELECT dept_id,MAX(salary) max_sal
    FROM emp
    GROUP BY dept_id
    HAVING MAX(salary)<5000;

八、22 节:SELECT 语句底层真实执行顺序(高频面试考点)

1. 开发者书写 SQL 的人为书写顺序

SELECT → DISTINCT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT

2.MySQL 引擎真实物理执行顺序(决定别名引用、子句可用范围)

  1. FROM:加载数据表、执行关联表连接,拿到原始数据源

  2. WHERE:逐行做行级过滤,淘汰不符合条件的数据行

  3. GROUP BY:按指定字段拆分数据分组,初始化每组聚合统计上下文

  4. HAVING:基于分组完成后的聚合结果,做分组级过滤(唯一能校验聚合结果的阶段)

  5. SELECT:计算字段表达式、给字段赋予别名、执行 DISTINCT 全局去重

  6. ORDER BY:对最终投影后的结果集做全局排序

  7. LIMIT:截断结果集,输出分页限定条数的数据

顺序衍生 3 条必懂规则

  1. WHERE 阶段早于 SELECT,WHERE 子句无法引用 SELECT 内自定义别名;HAVING 在分组阶段后,可引用分组内聚合计算结果;

  2. GROUP BY 前置过滤优先用 WHERE,能提前裁剪数据量,减少分组磁盘内存开销,不要把行级筛选全堆进 HAVING;

  3. ORDER BY 可以复用 SELECT 定义的字段别名,排序阶段在 SELECT 字段投影之后。

九、23 节:DQL 全章节知识点复盘总结

1. 子句职能 & 使用优先级总览

  1. FROM:数据源入口,所有查询逻辑的起始基准;

  2. WHERE(行前置过滤):过滤原始单行数据,不可写聚合函数,做早期数据裁剪优化性能;

  3. GROUP BY:拆分数据分组,适配部门、品类类批量统计需求;

  4. HAVING(分组后置过滤):校验聚合统计结果,解决 WHERE 无法筛选聚合值的局限;

  5. SELECT:决定最终对外暴露哪些字段,做字段别名、列运算、DISTINCT 去重;

  6. ORDER BY:统一规范结果排序规则,支撑列表顺序展示;

  7. LIMIT:做分页数据截断,适配前端分页列表交互场景。

2. 高频易错问题汇总

  1. NULL 匹配错误:不用=NULL,统一用IS NULL / IS NOT NULL;NULL 参与四则运算结果固定为 NULL;

  2. WHERE/HAVING 选型混淆:单行原始数据过滤选 WHERE;分组聚合后的统计值过滤必须选 HAVING;

  3. GROUP BY 字段不匹配:SELECT 非聚合字段必须归入 GROUP BY 分组字段,规避非确定性数据;

  4. 分页深分页性能劣化:大 offset 场景改用主键游标分页;排序固定依托主键保证分页数据不错乱;

  5. 模糊查询全通配前缀%xxx会使索引失效,百万级数据表禁止大范围前缀模糊检索。

3. 生产环境性能优化通用建议

  1. 杜绝线上业务SELECT *,按需枚举查询字段,降低网络传输与磁盘 IO 开销;

  2. WHERE、GROUP BY、ORDER BY、分页排序的高频字段提前创建适配索引,降低全表扫描概率;

  3. 能前置在 WHERE 做的数据过滤,绝不延后到 HAVING 做筛选,压缩分组阶段处理的数据体量;

  4. 超大数据量分页场景,放弃传统 offset 分页,改用「主键游标分页」(WHERE id > 上一页最后主键 LIMIT page_size),大幅降低数据库扫描行数。

结语

DQL 是数据库开发、后端接口开发、数据报表开发的核心基础,不只要掌握语法拼写,还要吃透底层执行顺序,区分 WHERE/HAVING、聚合函数、分组查询的适用边界,规避线上慢查询、分页错乱、分组数据异常等典型线上故障。后续进阶可拓展联表 JOIN 查询、子查询、窗口函数,完成复杂多表关联统计、排行类业务需求。


文档导出指引

你可以复制全文内容:

  1. Word 文档:新建空白 Word,粘贴全文,按标题层级设置「一级标题(章节大标题)、二级标题(小节标题)、正文、代码块( Courier New 字体)」排版后直接保存.docx

  2. Markdown 文档:新建后缀为.md文件,直接粘贴文本,可上传掘金、CSDN、个人博客站点发布;

  3. PDF 格式:Word 排版完成后,执行「另存为→导出为 PDF」即可生成 PDF 归档文档。

要不要我补充适配 CSDN 站点的标签、SEO 标题和段落配图建议,直接帮你完善成可一键发布的博客成品?

相关推荐
小心亦新1 小时前
STM32学习13 定时器1中断
stm32·嵌入式硬件·学习
我命由我123451 小时前
72 法则极简理解
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
qq_263_tohua2 小时前
第112期 CNN学习,不错的文章
学习
我想我不够好。2 小时前
满级的惩戒在范围
学习
xian_wwq3 小时前
【学习笔记】OpenAI 兼容 API 服务化:从协议到 LLM Gateway(19/35)
笔记·学习
辞旧 lekkk4 小时前
【Qt系统相关】鼠标事件
linux·开发语言·qt·学习·计算机外设·萌新
子非鱼94274 小时前
10-Flutter调用鸿蒙原生能力前置课:MethodChannel和PlatformView准备
学习·flutter·华为·harmonyos
小L~~~4 小时前
MLIR学习笔记
笔记·学习·mlir
从零开始的代码生活_5 小时前
C++ string 详解:常用接口、字符串算法与深拷贝实现
开发语言·c++·后端·学习·算法