news 2026/9/8 6:15:08

MySQL单表查询实战:从基础语法到综合练习

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL单表查询实战:从基础语法到综合练习

MySQL 单表查询,其实是整个 SQL 学习路线里性价比最高的一块。从大学课程、培训机构、到面试题,单表查询都是最先考、最常考、也最容易出细节坑的部分。很多同学觉得"单表查询不就是 SELECT + FROM + WHERE",等真正面对一道带条件、排序、分组、分页、NULL 判断的综合题时,反而写不流畅。这篇是 MySQL 系列的第 9 篇,专门用来做单表查询的集中练习。

本文会把练习环境、测试数据、查询语句、结果含义、常见报错全部走一遍。你可以直接复制 SQL 到自己的 MySQL 里跑,也可以先把练习题抄下来,自己写一遍再对答案。适合刚学完 SQL 基础、想巩固语法的初学者,也适合准备面试、想快速捡起 MySQL 查询能力的开发者。

先给一个全文速览:

能力项说明
适用数据库MySQL 5.7 / MySQL 8.0 均可
前置条件能连接到 MySQL 服务,有建库建表权限
核心语法SELECT / WHERE / LIKE / IN / BETWEEN / ORDER BY / LIMIT
进阶语法GROUP BY / HAVING / 聚合函数 / DISTINCT
练习数据自建员工表 emp,约 14 条记录
工具选择命令行、Navicat、MySQL Workbench 都可以
涉及接口本练习不涉及 API,重点是把 SQL 写对、跑通、看懂结果

如果你 MySQL 还没装好,建议先按对应系统的安装教程把环境搭好,确保能通过命令行或图形工具连上服务,再开始下面的操作。

1. 单表查询练习前的环境准备

开始之前,先确认你的 MySQL 服务已经正常启动。命令行登录:

mysql -u root -p

输入密码后,能进入mysql>提示符就算成功。如果你用的是 Navicat 或 MySQL Workbench,直接新建连接,测试连通性即可。

接下来,我们要把练习用的数据库和表准备好。整个过程都在你本机或你自己的测试库中进行,避免动到生产环境的数据。我建议单独建一个库,方便后面练习完直接删除。

CREATE DATABASE IF NOT EXISTS company DEFAULT CHARACTER SET utf8mb4; USE company;

这里指定utf8mb4字符集,主要原因是后续练习中会涉及中文排序、中文模糊匹配,字符集不对会踩很多莫名其妙的坑。

然后建员工表:

DROP TABLE IF EXISTS emp; CREATE TABLE emp ( emp_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '员工编号', emp_name VARCHAR(50) NOT NULL COMMENT '姓名', gender CHAR(1) DEFAULT '男' COMMENT '性别', dept VARCHAR(30) COMMENT '部门', job VARCHAR(30) COMMENT '岗位', salary DECIMAL(10,2) COMMENT '月薪', bonus DECIMAL(10,2) COMMENT '奖金', city VARCHAR(30) COMMENT '城市', hire_date DATE COMMENT '入职日期' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工表';

表结构不要太复杂,保留练习单表查询需要的核心字段即可。这里有数值类型、字符串类型、日期类型,还有允许为空的bonus字段,方便后续练习NULL判断。

插入测试数据:

INSERT INTO emp (emp_name, gender, dept, job, salary, bonus, city, hire_date) VALUES ('张三', '男', '技术部', 'Java开发', 15000.00, 3000.00, '北京', '2020-03-15'), ('李四', '女', '技术部', '前端开发', 13000.00, 2500.00, '上海', '2021-07-01'), ('王五', '男', '产品部', '产品经理', 18000.00, 5000.00, '北京', '2018-11-20'), ('赵六', '女', '设计部', 'UI设计师', 11000.00, 1500.00, '深圳', '2022-01-10'), ('钱七', '男', '技术部', '测试工程师', 10000.00, 1000.00, '广州', '2022-06-15'), ('孙八', '女', '运营部', '运营专员', 9500.00, 800.00, '北京', '2023-02-28'), ('周九', '男', '技术部', '运维工程师', 14000.00, 2000.00, '上海', '2019-09-01'), ('吴十', '女', '人事部', 'HRBP', 12000.00, NULL, '北京', '2021-12-05'), ('郑一', '男', '财务部', '会计', 10500.00, 1200.00, '杭州', '2020-08-17'), ('冯二', '女', '销售部', '销售经理', 20000.00, 8000.00, '广州', '2017-04-12'), ('陈三', '男', '销售部', '销售顾问', 9000.00, 3500.00, '深圳', '2022-10-08'), ('褚四', '女', '技术部', '数据分析师', 16000.00, 2800.00, '上海', '2019-05-23'), ('卫五', '男', '产品部', '运营助理', 8000.00, 500.00, '北京', '2023-07-10'), ('蒋六', '女', '设计部', '交互设计师', 12500.00, 1800.00, '杭州', '2021-03-30');

插完后先看一遍全量数据,确认没有任何问题:

SELECT * FROM emp;

这里有一个很容易犯的错误:很多人插入数据后发现中文变成乱码,或者插入直接报错。绝大多数原因是客户端连接字符集和表字符集不一致。可以先设置本次连接的字符集再执行插入:

SET NAMES utf8mb4;

后面所有练习,都基于这张 14 条记录的员工表。如果你想自己加数据,也可以,但要注意bonus字段保留几条NULL,后面专门针对它出题。

2. 单表查询基础:SELECT 与 WHERE

2.1 查询指定列

先从最简单的开始。查询所有员工的姓名、岗位、月薪:

SELECT emp_name, job, salary FROM emp;

结果是三列,行数与全表一致。这里要理解一个关键点:SELECT 决定的是查询哪些列,WHERE 决定的是过滤哪些行,两者职责不同,不要混在一起想。

查看所有不重复的部门列表:

SELECT DISTINCT dept FROM emp;

DISTINCT会去掉重复值。从这个结果能看到当前表里总共有几个部门,后面分组统计时还会用到。注意DISTINCT是对后面所有列的组合去重,不是只对第一个列去重。如果写SELECT DISTINCT dept, city FROM emp,它要求部门加城市的组合不重复。

2.2 WHERE 条件过滤

找出月薪大于等于 15000 的员工:

SELECT emp_name, job, salary FROM emp WHERE salary >= 15000;

从数据看,符合条件的应该是王五、冯二、褚四这几个人。条件判断支持常规的比较运算符:>>=<<==!=<>。比较运算符两边可以是列名,也可以是常量,甚至是另一个字段。

比如,查奖金比月薪高的员工,这里本身就是单表内两个字段之间的比较:

SELECT emp_name, salary, bonus FROM emp WHERE bonus > salary;

这类"字段与字段比较"的题目非常容易出现在笔试题里,因为很多人的思路还停留在"字段与常量比较",想不到直接写bonus > salary

多个条件组合时,用ANDOR连接:

SELECT emp_name, dept, salary FROM emp WHERE dept = '技术部' AND salary > 12000;

这里要注意运算符优先级的坑。AND的优先级高于OR,所以如果一个 SQL 里同时出现ANDOR,又想要不同的逻辑组合,就一定要加括号。比如:

SELECT emp_name, dept, salary FROM emp WHERE (dept = '技术部' OR dept = '产品部') AND salary > 12000;

不加括号的话,SQL 会先执行dept = '技术部' OR dept = '产品部' AND salary > 12000,由于AND优先级高,结果等价于dept = '技术部' OR (dept = '产品部' AND salary > 12000),查询语义完全不一样。这是一种非常常见又隐蔽的查询错误,自己写 SQL 时一定要养成加括号的习惯。

2.3 基础练习

先自己写,再往下看答案。

题目一:查询销售部所有员工的姓名、岗位、城市。

题目二:查询月薪在 12000 到 16000 之间的员工姓名和工资。

参考答案:

SELECT emp_name, job, city FROM emp WHERE dept = '销售部';
SELECT emp_name, salary FROM emp WHERE salary >= 12000 AND salary <= 16000;

第二题后面还会讲到BETWEEN AND写法,但这道题先让你体会一下AND连接两个条件的感觉。

3. 模糊查询与范围查询

3.1 LIKE 模糊匹配

模糊查询在单表查询里非常重要,因为真实业务场景中,你经常只知道某个名字的一部分。比如,查所有姓"张"的员工:

SELECT emp_name, job FROM emp WHERE emp_name LIKE '张%';

%代表任意多个字符,包括零个字符。所以'张%'能匹配到"张三"。如果写成'%张%',它匹配的是姓名中间任何位置带"张"的人,这种写法在搜索功能里更常用。

下划线_只匹配一个任意字符。比如,查名字里第二字是"三"的人:

SELECT emp_name FROM emp WHERE emp_name LIKE '_三%';

这个_匹配"张"这个位置,是第二个字,%匹配后面的内容。%_的区别必须分清楚,面试的时候经常被问到。

3.2 BETWEEN AND 与 IN

查月薪在 12000 到 16000 之间的员工,可以用BETWEEN AND

SELECT emp_name, salary FROM emp WHERE salary BETWEEN 12000 AND 16000;

注意BETWEEN AND是包含边界值的,也就是包含 12000 和 16000 本身。如果你不希望包含边界,还是要用>=<手动组合。这一点在按时间范围查询时特别容易被忽略,很多人在统计月初月末数据时,因为边界条件没写对,导致数据多一条或少一条。

查城市为北京、上海、广州的员工:

SELECT emp_name, city FROM emp WHERE city IN ('北京', '上海', '广州');

IN后面是一个列表,等价于city = '北京' OR city = '上海' OR city = '广州'。它是多个 OR 条件的语法糖,但可读性更好。反过来,想排除这几个城市的员工,写成:

SELECT emp_name, city FROM emp WHERE city NOT IN ('北京', '上海', '广州');

3.3 NULL 的判断

这是最容易出错的一个点。查询奖金为空的员工:

SELECT emp_name, bonus FROM emp WHERE bonus IS NULL;

注意,bonus = NULL这种写法在 MySQL 里不会报错,但永远查不出数据。NULL不是一个值,它表示"未知",用=去比较未知结果仍然是未知,所以在条件判断中不会为真。判断空值必须用IS NULL,判断非空用IS NOT NULL

你还会遇到另一个问题:用IFNULL函数可以在查询结果里把NULL转成指定值。比如:

SELECT emp_name, IFNULL(bonus, 0) AS actual_bonus FROM emp;

这里的AS是给查询结果列取别名。注意IFNULL只是在查询展示时把NULL转换成 0,并没有真正修改原始数据。这个点在后端查询里非常实用,因为很多语言在处理NULL时会类型报错。

3.4 练习与排查

题目三:查询岗位上带有"开发"两个字的员工。

题目四:查询奖金不是空的员工。

参考答案:

SELECT emp_name, job FROM emp WHERE job LIKE '%开发%';
SELECT emp_name, bonus FROM emp WHERE bonus IS NOT NULL;

如果你查LIKE写对了却查不到中文,先检查字符集,再检查数据里是否包含空格或全半角不一致。中文数据里最隐蔽的问题是搜索条件里出现全角空格,肉眼根本看不出来。建议用SELECT LENGTH(emp_name) FROM emp检查字段长度是否异常。

4. 排序与分页

4.1 ORDER BY 基本用法

单表查询如果没有排序,结果顺序是不保证的,尤其是 InnoDB 存储引擎下,记录在物理文件中的顺序可能和数据插入顺序不一致。所以想让结果具备可预测性,必须显式加ORDER BY

按月薪从高到低排序:

SELECT emp_name, salary FROM emp ORDER BY salary DESC;

DESC表示降序,ASC表示升序,升序是默认值,所以只写ORDER BY salary就是升序。

多字段排序时,先写优先排序的字段。比如先按部门升序,再按薪资降序:

SELECT dept, emp_name, salary FROM emp ORDER BY dept ASC, salary DESC;

这个查询结果的逻辑是:先按部门字母或字符编码顺序排好,同一部门内部再按工资从高到低排。这里想强调一个实际开发中常见的误区:多字段排序时,如果前一个字段已经能区分顺序,后一个字段就不会生效;只有前一个字段值相同时,后一个字段才起作用。你在刚学的时候容易想成"每个字段独立排序再合并",实际不是这样。

4.2 中文排序问题

如果表字符集是utf8mb4,直接用ORDER BY emp_name ASC排序中文时,一般情况下 MySQL 是按 Unicode 编码排序的,并不按照拼音或偏旁部首来排,结果看起来经常"不符合直觉"。想在 MySQL 5.7 里按拼音排序,可以借助CONVERT

SELECT emp_name FROM emp ORDER BY CONVERT(emp_name USING gbk) ASC;

MySQL 8.0 里由于默认字符集和排序规则已经有改进,普通场景下直接排序基本可用,但如果你遇到中文排序结果不符合预期的场景,仍然可以用CONVERT(emp_name USING gbk)这种处理方式。这里不展开深入,只要记住"中文排序异常时,先改排序规则这个方向"就可以了。

4.3 LIMIT 分页

分页是后端联表查询之前必须掌握的技能。每页显示 5 条数据,查询第一页:

SELECT emp_id, emp_name, salary FROM emp ORDER BY salary DESC LIMIT 0, 5;

LIMIT 0, 5的意思是跳过 0 条,取 5 条。第二页:

SELECT emp_id, emp_name, salary FROM emp ORDER BY salary DESC LIMIT 5, 5;

偏移量计算公式是(页码 - 1) * 每页条数。这个公式几乎是后端开发写分页时必用的,但要注意,如果OFFSET非常大,比如几百万行后再取数据,MySQL 仍然要扫描并丢弃前面大量行,性能会很差,这就是"深分页"问题。这个问题在单表查询阶段只需了解,真正处理时可以用WHERE id > 上一页最大id的方式替代。

4.4 排序与分页练习

题目五:查询工资排名第 6 到第 10 的员工姓名和工资。

参考答案:

SELECT emp_name, salary FROM emp ORDER BY salary DESC LIMIT 5, 5;

排序和分页经常一起出现,因为分页本身基于排序结果才有意义。如果你没有写ORDER BY就直接LIMIT,拿到的数据顺序是不确定的,每次运行可能一样也可能不一样。排查线上分页数据"变来变去"的问题时,第一件事就是检查排序字段是否完整。

5. 聚合函数与分组统计

5.1 常用聚合函数

聚合函数是对一组值执行计算并返回一个单一值的函数。最常用的几个是:

SELECT COUNT(*) AS total_count, SUM(salary) AS total_salary, AVG(salary) AS avg_salary, MAX(salary) AS max_salary, MIN(salary) AS min_salary FROM emp;

COUNT(*)统计的是行数,COUNT(bonus)统计的是 bonus 字段非 NULL 的行数。这一点要格外注意,如果你是统计奖金不为空的人数,应该用COUNT(bonus),但如果你只是想统计表里总共几条记录,用COUNT(*)。两者在bonus字段有 NULL 时结果完全不同。

SUMAVG会自动忽略 NULL 值。AVG(bonus)等于SUM(bonus)/COUNT(bonus),这个细节也会影响统计结果的含义。

5.2 GROUP BY 分组统计

分组的核心作用是把数据按某个维度拆分,再对每个分组做聚合计算。统计每个部门的员工人数:

SELECT dept, COUNT(*) AS cnt FROM emp GROUP BY dept;

统计每个城市的平均工资:

SELECT city, AVG(salary) AS avg_salary FROM emp GROUP BY city;

这里有一个所有 MySQL 初学者都会遇到的坑:如果查询列表里出现了非聚合列,但它没有包含在GROUP BY子句中,在 MySQL 5.7 且开启ONLY_FULL_GROUP_BY模式时,会直接报错。例如下面的写法在很多数据库里都不能执行:

SELECT dept, emp_name, COUNT(*) FROM emp GROUP BY dept;

因为emp_name既不在GROUP BY中,也不是聚合函数的结果。当部门里有多个员工时,到底展示哪个emp_name是没有语义的。开发时遇到this is incompatible with sql_mode=only_full_group_by这类报错,就要检查是不是 SELECT 中混入了非聚合字段。更稳妥的做法是:查询列表里只保留分组字段和聚合函数,其他字段如果想要,可以通过子查询或另一次查询实现。

5.3 HAVING 过滤分组

WHERE是在分组前过滤原始行,HAVING是在分组后过滤分组。统计平均工资超过 12000 的部门:

SELECT dept, AVG(salary) AS avg_salary FROM emp GROUP BY dept HAVING AVG(salary) > 12000;

这里可以直观看到 SQL 的执行顺序大概是:FROM找表,WHERE过滤行,GROUP BY分组,HAVING过滤分组,SELECT计算输出列,ORDER BY排序,LIMIT分页。理解这个顺序,是写复杂查询的基础,也是排查各种"为什么结果不对"问题的钥匙。

HAVING后面能不能用SELECT中的别名?MySQL 中HAVING是可以识别别名的,但为了可读性,更推荐直接写原始表达式,因为不同的数据库对HAVING别名支持情况并不一致。

5.4 DISTINCT 与 GROUP BY

去重有两种方式:SELECT DISTINCT dept FROM empSELECT dept FROM emp GROUP BY dept。这两者结果相似,但思路完全不同。DISTINCT是去重输出,GROUP BY是分组统计。如果只是想知道有哪几个部门,用DISTINCT更直观;如果还要统计每个部门的人数或工资,那就必须用GROUP BY

统计每个部门的最高工资并降序排列:

SELECT dept, MAX(salary) AS max_salary FROM emp GROUP BY dept ORDER BY max_salary DESC;

这里SELECT中定义了别名max_salaryORDER BY中使用别名是可以的,因为ORDER BYSELECT之后执行。但WHERE中不能使用别名,因为WHERESELECT之前执行。如果你在WHERE里写WHERE max_salary > 10000,MySQL 会报"Unknown column"错误。这个执行顺序是面试常考的点,也是写复杂 SQL 时最容易疑惑的地方。

5.5 分组统计练习

题目六:统计每个部门的人数,按人数降序排列。

题目七:统计部门人数大于等于 2 的部门。

参考答案:

SELECT dept, COUNT(*) AS cnt FROM emp GROUP BY dept ORDER BY cnt DESC;
SELECT dept, COUNT(*) AS cnt FROM emp GROUP BY dept HAVING COUNT(*) >= 2;

第二题就是先GROUP BY dept统计人数,再用HAVING过滤。注意这里不能把COUNT(*) >= 2写到WHERE里,因为WHERE执行的时候分组还没发生,此时COUNT(*)根本还没计算出来。

6. 单表查询常见错误与排查

问题现象可能原因排查方式解决方案
查询不出 NULL 记录用了= NULL检查条件是否写成IS NULL改为WHERE bonus IS NULL
中文模糊查询查不到字符集不一致或存在全角空格LENGTH()检查字段长度设置SET NAMES utf8mb4,清洗空格
中文排序不符合预期utf8mb4默认排序规则不支持拼音排序查看当前排序规则使用CONVERT(字段 USING gbk)排序
分组统计报only_full_group_by错误SELECT 中有非聚合列未包含在 GROUP BY检查报错的确切列只保留分组字段和聚合函数
WHERE 中使用别名报未知列执行顺序先 WHERE 后 SELECT确认是否在 WHERE 中用别名把别名条件移到 HAVING 或以原始列重写
LIMIT 100000, 20查询越来越慢深分页导致大量扫描EXPLAIN观察扫描行数改为基于主键和上一页最大 ID 的查询

这些坑每一个我都见过不止一次出现在线上问题和面试题里。单独看每个都简单,但实际写查询的时候,各种细节叠加在一起,问题就变得很难定位。排查 SQL 问题的时候,最好的方式是把查询拆成一步一步:先跑SELECT * FROM emp,再逐步加WHERE,加GROUP BY,加HAVING,加ORDER BY,最后加LIMIT,每一步观察结果是否符合预期,很快就能定位到是哪一步出了问题。

7. 单表查询的性能观察:EXPLAIN

在练习阶段就建立用EXPLAIN的习惯,对后面优化帮助很大。EXPLAIN不会真正执行查询,而是展示 MySQL 执行这条 SQL 的大致计划。最基本的用法是:

EXPLAIN SELECT * FROM emp WHERE dept = '技术部';

返回结果里重点看几个字段:

字段含义怎么看
type访问类型一般为 ALL、range、ref、eq_ref、const 等,从差到好大致顺序为 ALL、index、range、ref、const
possible_keys可能用到的索引如果为 NULL,说明没有可用索引
key实际使用的索引如果为 NULL,说明没用索引
rows预计扫描行数越小越好
Extra额外信息出现Using filesort表示文件排序,可能需要优化排序字段

刚刚那条dept = '技术部',如果没有给dept建索引,type一般是ALLrows是 14。给dept建一个普通索引后:

CREATE INDEX idx_emp_dept ON emp(dept);

再执行EXPLAINtype通常会变成refrows会明显减少。这个变化过程比直接背优化理论直观得多。查询完成后,为了保持练习环境干净,可以删除测试索引:

DROP INDEX idx_emp_dept ON emp;

需要强调的是,EXPLAIN只是一个执行计划估算,它不代表真实执行时间。有时候typeALL,但因为表很小,实际也很快;有时候typeref,但访问的行数非常多,也不一定最优。所以练习阶段重点不是抠每个参数,而是建立"查询能不能走索引、大概扫描多少行"这个意识。后面学多表联查和慢查询优化时,这个底子很重要。

8. 单表查询综合练习

前面按知识点拆开练习,下面给一套综合题目,建议不要看任何参考,按顺序独立写完,再对照参考答案。

题目八:查询技术部工资大于 12000 的员工姓名和工资,按工资降序排列。

题目九:统计各部门工资总和,输出高于 25000 的部门。

题目十:查询 2020 年之后入职的员工信息。

参考答案:

SELECT emp_name, salary FROM emp WHERE dept = '技术部' AND salary > 12000 ORDER BY salary DESC;
SELECT dept, SUM(salary) AS total_salary FROM emp GROUP BY dept HAVING SUM(salary) > 25000 ORDER BY total_salary DESC;
SELECT * FROM emp WHERE hire_date >= '2020-01-01';

第十题里,日期比较在 MySQL 中可以直接用字符串形式,MySQL 会自动把字符串转换为日期进行比较。所以记住一个通用的经验法则:在条件判断里,字段类型是日期,就直接给标准格式字符串;字段类型是数字,尽量给数字;字段类型是字符串,就加引号,不要自作聪明做隐式类型转换。如果你写WHERE salary = '10000',虽然在 MySQL 中多数情况下也能得到结果,但当字段有索引时,字符串和数字比较可能导致索引失效,进而产生全表扫描,这类隐式转换问题在慢查询优化中是一个非常经典的反面教材。

9. 最佳实践与学习建议

先建练习专用库,不要直接在生产环境甚至业务库上反复执行DROP TABLE和大量INSERT操作。练习结束后,想清空这个库可以直接执行DROP DATABASE company,不会影响其他数据。

所有练习脚本建议用 SQL 文件保存,而不是只在客户端里敲完就没了。包括建表、插入、每个查询题目和对应的答案,保存成一个带编号的文件,比如01_create_table.sql02_insert_data.sql03_query_exercise.sql,这样以后复习或换电脑都能快速恢复环境。命令行执行 SQL 文件的方式:

mysql -u root -p company < ./query_exercise.sql

写查询时养成格式化习惯:关键字大写或统一小写都可以,但一个项目里最好统一;SELECT的每个字段放在单独一行;多个查询条件用括号明确优先级。这样不仅方便自己排查,代码评审时别人也更容易看懂。

关于字符集,建库时显式指定utf8mb4,连接时执行SET NAMES utf8mb4,这是避免中文乱码最稳妥的组合。另外,文档和代码注释里不要写一堆"必会"、"重点"之类的套话,把每条 SQL 解决什么问题写清楚就够了。

如果后面要接入 Java、Python 等编程语言,这套 SQL 语句可以原样放到 JDBC、PyMySQL、MyBatis 的 SQL 语句中。但要注意,不要把这些练习数据直接用于真实业务系统,真实系统的数据往往有主外键约束、逻辑删除字段、多租户隔离等额外要求,单表查询练习阶段可以先不考虑这些。

10. 总结与下一步

单表查询练到位了,真正跨进多表查询时会顺畅很多。因为你已经知道了 WHERE 执行顺序、GROUP BY 和 HAVING 的边界、NULL 判断、聚合函数取舍、索引和 EXPLAIN 的基本概念,这些是所有复杂查询的公共底座。

建议你先完整跑一遍本文的建表和插入 SQL,然后不参考答案,把十道练习题目都写一遍。重点验证三件事:第一,NULL 的判断是否真的理解;第二,GROUP BY+HAVINGWHERE的执行顺序是否清楚;第三,碰到only_full_group_by报错时,能不能自己读懂报错含义并调整查询。

最容易踩的坑还是这几处:$= NULL$永远查不到数据、WHERE里用别名导致未知列、中文排序结果不符合预期、分组查询混入非聚合列。如果你在自己的练习中遇到这些问题,回到对应章节检查即可。

下一步可以直接进入多表查询练习,也就是INNER JOINLEFT JOIN、子查询这几个方向。学的时候记得带着单表查询的执行顺序思维,你会发现多表查询的很多"奇怪现象",本质上还是单表查询规则的延伸。

这篇文章可以按 F12 收藏或者复制到自己的笔记里,遇到查询语法问题时,回来对照执行顺序和排查表,比盲猜快得多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 6:14:59

智能合约安全实战指南:从代码审计到经济博弈的攻防实践

区块链行业这几年最不缺的就是新闻&#xff0c;从DeFi的大起大落到NFT的一夜爆红&#xff0c;再到各种跨链桥被反复攻击&#xff0c;背后始终绕不开一个核心话题——智能合约安全。我自己在审计和开发一线摸爬滚打了不少年头&#xff0c;见过太多项目在代码细节上栽跟头&#x…

作者头像 李华
网站建设 2026/9/8 6:14:53

OTFS接收机低复杂度LMMSE-PIC均衡器:原理与工程实现

简介&#xff1a;面向正交时频空间调制&#xff08;OTFS&#xff09;通信体制的研究人员与高年级研究生&#xff0c;这份代码资源聚焦高移动性场景下的接收机均衡难题。由于OTFS符号在时频双选择性信道中会遭受二维干扰&#xff0c;传统线性均衡的矩阵求逆开销极大&#xff0c;…

作者头像 李华
网站建设 2026/9/8 6:14:17

SQL LIKE模糊查询的陷阱:从慢查询到索引优化与安全转义

我第一次意识到 SQL 里的 LIKE 不是“省事工具”&#xff0c;是在一次线上慢查询排查里。业务方想按订单号前缀查最近一批异常单据&#xff0c;SQL 写得很自然&#xff1a;SELECT * FROM orders WHERE order_no LIKE 202406%。查询条件看起来没问题&#xff0c;但执行计划显示它…

作者头像 李华
网站建设 2026/9/8 6:13:38

现在主流的AI写作辅助平台有哪些品牌?聊聊真实使用体验

每到期末、毕业答辩、课题申报阶段&#xff0c;很多学生都会陷入论文写作的困境&#xff1a;选题毫无头绪、大纲搭建逻辑混乱、正文撰写耗时长、参考文献格式出错、查重重复率偏高、AIGC检测告警、本校论文排版标准复杂。依靠纯人工从零开始撰写、一遍遍修改格式和降重&#xf…

作者头像 李华
网站建设 2026/9/8 6:11:46

2026年B站视频转笔记AI工具横评:五款主流工具实测对比

我现在下了一个判断&#xff1a;把B站视频变成结构化笔记这件事&#xff0c;2026年已经不算什么新鲜功能了&#xff0c;但“到底该用哪个工具”反倒成了最难回答的问题。过去两年我也没少折腾AI笔记工具&#xff0c;从最早拿语音转写软件硬怼视频音频&#xff0c;到现在随便一个…

作者头像 李华
网站建设 2026/9/8 6:10:32

响应式餐饮网页源码实战:从HTML结构到移动端适配全解析

简介&#xff1a;一套意大利风味餐厅响应式网页的完整HTML源码&#xff0c;面向Web前端初学者、H5爱好者以及需要快速搭建餐饮品牌展示站的中小企业。源码基于HTML5、CSS3与JavaScript&#xff0c;集成Bootstrap、animate.css、Magnific Popup等常用前端库&#xff0c;涵盖产品…

作者头像 李华