一、多表查询核心概念铺垫
先明确核心术语:
- 关系表:有等值关联字段的表(如hzuser的jiejiNum和jieji的jiejiNum),关系型数据库的核心特征。
- 等值连接条件:多表查询时必须通过 “表 A. 字段 = 表 B. 字段” 消除笛卡尔积,是多表查询的基础。
二、逐行代码拆解(单词含义 + 语法作用)
1. WHERE 方式多表查询
SELECT * FROM hzuser as h,jieji as j WHERE h.jiejiNum=j.jiejiNum;
关键词 / 符号 | 英文含义 | 语法作用 |
SELECT | 选择 | 数据查询的起始关键字,指定要查询的列 |
* | 通配符(all) | 表示查询所有列,替代逐个列名书写 |
FROM | 从… 来源 | 指定查询的数据源表 |
hzuser | 表名(会员表) | 第一个关联表(自定义命名,如 “会员信息表”) |
as | 作为(alias) | 给表起别名的关键字,可省略 |
h | 表别名(hzuser) | 简化表名书写,后续可用h.字段代替hzuser.字段 |
, | 分隔符 | 分隔多个关联表,表示多表笛卡尔积关联(需 WHERE 条件过滤) |
jieji | 表名(阶级表) | 第二个关联表(自定义命名,如 “会员阶级表”) |
j | 表别名(jieji) | 简化jieji表名书写 |
WHERE | 哪里 | 筛选条件关键字,此处用于指定多表连接的等值条件 |
h.jiejiNum | 表别名。字段名 | hzuser表的jiejiNum字段(阶级编号),关联字段 |
= | 等于 | 等值连接运算符,核心:让两个表的关联字段匹配 |
j.jiejiNum | 表别名。字段名 | jieji表的jiejiNum字段(阶级编号),与h.jiejiNum形成等值关联 |
整行含义:从hzuser(别名 h)和jieji(别名 j)两张表中,查询所有列的数据,仅保留hzuser的jiejiNum等于jieji的jiejiNum的记录(消除笛卡尔积)。
2. JOIN ON 方式多表查询
SELECT * FROM hzuser as h join jieji as j on h.jiejiNum=j.jiejiNum;
关键词 / 符号 | 英文含义 | 语法作用 |
JOIN | 连接 | 多表连接的关键字(内连接,默认 INNER JOIN,可省略 INNER) |
ON | 在… 条件上 | 专门指定多表连接的等值条件(JOIN 方式的连接条件必须写在 ON 后,而非 WHERE) |
其余(SELECT/*/FROM/as 等) | 同上文 | 同上文 |
整行含义:用标准 JOIN ON 语法(内连接)查询hzuser和jieji的所有列,连接条件是h.jiejiNum=j.jiejiNum,效果与 WHERE 方式一致,但语义更清晰(连接条件和筛选条件分离)。
3. 自连接(一张表变两张表)
SELECT * FROM hzuser x JOIN hzuser y ON x.manager=y.hzUserNum;
关键词 / 符号 | 英文含义 | 语法作用 |
hzuser x | 表名 + 别名 x | 将hzuser表虚拟为 “下属表”(x 代表下属) |
hzuser y | 表名 + 别名 y | 将hzuser表虚拟为 “领导表”(y 代表领导) |
x.manager | 下属表的 manager 字段 | hzuser表中 “下属的领导编号” 字段 |
y.hzUserNum | 领导表的 hzUserNum 字段 | hzuser表中 “领导的会员编号” 字段(与下属的 manager 匹配) |
整行含义:将hzuser表拆分为 “下属表 x” 和 “领导表 y”,通过 “下属的领导编号(x.manager)= 领导的会员编号(y.hzUserNum)” 关联,查询所有列(显示每个下属对应的领导信息)。
4. 自连接(自定义显示列)
SELECT x.name as '下属' , y.name as '领导' from hzuser x join hzuser y on x.manager=y.hzUserNum;
关键词 / 符号 | 英文含义 | 语法作用 |
x.name | 下属表的 name 字段 | 下属的姓名 |
as '下属' | 作为 “下属” | 给列起中文别名,提升可读性 |
y.name | 领导表的 name 字段 | 领导的姓名 |
as '领导' | 作为 “领导” | 给列起中文别名 |
整行含义:自连接hzuser表,仅查询 “下属姓名” 和 “领导姓名”,并分别命名为 “下属” 和 “领导”,语义更直观。
5. 左连接(保留左表所有数据)
SELECT x.name as '下属' , y.name as '领导' from hzuser x left join hzuser y on x.manager=y.hzUserNum;
关键词 / 符号 | 英文含义 | 语法作用 |
LEFT JOIN | 左连接 | 保留左表(x 表,下属表)的所有记录,右表(y 表,领导表)无匹配则显示 NULL |
整行含义:自左连接hzuser表,查询所有下属的姓名,即使某个下属没有领导(x.manager 为 NULL),也会显示该下属,领导姓名列显示 NULL(内连接会过滤无领导的下属)。
6. 多表查询 + 筛选(WHERE 方式)
SELECT * FROM hzuser h ,jieji jj WHERE h.jiejiNum =jj.jiejiNum AND jj.jname='平民阶级';
关键词 / 符号 | 英文含义 | 语法作用 |
AND | 和 | 逻辑运算符,连接多个筛选条件(同时满足) |
jj.jname | 阶级表的 jname 字段 | 阶级名称字段 |
'平民阶级' | 字符串常量 | 筛选条件的值(注意字符串需用单引号包裹) |
整行含义:先通过h.jiejiNum=jj.jiejiNum关联hzuser和jieji表,再筛选出jieji表中jname为 “平民阶级” 的所有记录(显示平民阶级的会员信息)。
7. 多表查询 + 筛选(JOIN ON 方式)
SELECT * FROM hzuser h join jieji jj on h.jiejiNum=jj.jiejiNum WHERE jj.JNAME='平民阶级';
关键词 / 符号 | 英文含义 | 语法作用 |
WHERE | 哪里 | 此处用于筛选(而非连接),JOIN ON 负责连接,WHERE 负责过滤结果 |
整行含义:先通过 JOIN ON 关联两张表,再筛选出阶级名称为 “平民阶级” 的记录(效果与上一行一致,但语义更优:连接条件和筛选条件分离)。
8. 自连接 + 筛选(平民阶级的领导)
SELECT * from hzuser x join hzuser y on x.manager=y.hzUserNum AND x.jiejiNum=30;
关键词 / 符号 | 英文含义 | 语法作用 |
AND x.jiejiNum=30 | 和 | 在连接条件中增加筛选:仅匹配 “下属的阶级编号为 30(平民阶级)” 的记录 |
整行含义:自连接查询时,仅筛选出 “下属阶级编号为 30(平民阶级)” 的下属及其对应的领导信息。
9. 子查询作为表(派生表)
SELECT * FROM
(SELECT h.hzUserNum,h.manager,h.name,jj.JNAME from hzuser h join jieji jj on h.jiejiNum =jj.jiejiNum WHERE jj.JNAME='平民阶级') as x
join (SELECT hz.hzUserNum ,hz.`name` from hzuser hz) as y on x.hzUserNum =y.hzUserNum;
关键词 / 符号 | 英文含义 | 语法作用 |
(SELECT ...) | 子查询 | 括号内的查询结果作为 “派生表”,需起别名才能被外层查询引用 |
as x | 派生表别名 x | 第一个子查询结果的别名(平民阶级会员表) |
as y | 派生表别名 y | 第二个子查询结果的别名(所有会员的编号和姓名表) |
x.hzUserNum=y.hzUserNum | 等值连接 | 关联两个派生表(平民阶级会员编号 = 所有会员编号) |
整行含义:
- 内层子查询 1:查询平民阶级会员的编号、领导编号、姓名、阶级名称,作为派生表 x;
- 内层子查询 2:查询所有会员的编号和姓名,作为派生表 y;
- 外层查询:关联 x 和 y,查询所有列(实际是冗余查询,效果等价于直接查平民阶级会员信息)。
10. 子查询作为条件(单行子查询)
SELECT name ,userSal from hzuser WHERE userSal=(SELECT max(userSal) from hzuser);
关键词 / 符号 | 英文含义 | 语法作用 |
userSal | 字段名(薪水) | 会员薪水字段 |
= | 等于 | 单行子查询的运算符(子查询返回唯一值) |
SELECT max(userSal) | 选择最大值 | 子查询:计算hzuser表中userSal的最大值 |
max() | 最大值(maximum) | 聚合函数,计算指定列的最大值 |
整行含义:查询薪水等于 “所有会员最高薪水” 的会员姓名和薪水。
11. 筛选非空值(找有领导的人)
SELECT * from hzuser WHERE manager is not null;
关键词 / 符号 | 英文含义 | 语法作用 |
manager | 字段名(领导编号) | 会员的领导编号字段 |
IS NOT NULL | 不是空值 | 空值判断运算符(NULL 不能用=判断,必须用 IS NULL/IS NOT NULL) |
整行含义:查询所有 “有领导(manager 字段非空)” 的会员信息。
12. 去重查询(找所有领导编号)
SELECT DISTINCT manager from hzuser WHERE manager is not null;
关键词 / 符号 | 英文含义 | 语法作用 |
DISTINCT | 不同的(distinct) | 去重关键字,消除查询结果中的重复行(仅保留唯一的领导编号) |
整行含义:查询所有非空的领导编号,并去重(得到所有领导的编号列表)。
13. IN 子查询(找所有领导)
SELECT * FROM hzuser WHERE hzUserNum in (SELECT DISTINCT manager from hzuser WHERE manager is not null);
关键词 / 符号 | 英文含义 | 语法作用 |
IN | 在… 里面 | 多值匹配运算符,判断hzUserNum是否在子查询返回的列表中 |
整行含义:查询 “会员编号(hzUserNum)存在于领导编号列表中” 的会员(即所有领导的信息)。
14. NOT IN 子查询(找非领导)
SELECT * FROM hzuser WHERE hzUserNum not in (SELECT DISTINCT manager from hzuser WHERE manager is not null);
关键词 / 符号 | 英文含义 | 语法作用 |
NOT IN | 不在… 里面 | 多值不匹配运算符,判断hzUserNum不在子查询返回的列表中 |
整行含义:查询 “会员编号不在领导编号列表中” 的会员(即非领导的普通会员)。
15. 聚合函数子查询(找高于平均薪水的人)
SELECT * from hzuser WHERE userSal>(SELECT Avg(userSal) from hzuser);
关键词 / 符号 | 英文含义 | 语法作用 |
> | 大于 | 比较运算符,判断薪水高于子查询结果 |
Avg() | 平均值(average) | 聚合函数,计算指定列的平均值 |
整行含义:查询薪水高于 “所有会员平均薪水” 的会员信息。
16. 子查询作为表(FROM 子句中的派生表)
SELECT * from hzuser hz join(SELECT DISTINCT manager from hzuser WHERE manager is not null) as ld on hz.hzUserNum=ld.manager;
关键词 / 符号 | 英文含义 | 语法作用 |
join (SELECT ...) as ld | 连接派生表 | 将子查询结果(领导编号列表)作为派生表 ld,与hzuser关联 |
ld.manager | 派生表 ld 的 manager 字段 | 子查询返回的领导编号字段 |
整行含义:将 “领导编号列表” 作为派生表 ld,与hzuser表关联,查询所有领导的信息(效果与 IN 子查询一致)。
17. 子查询在 SELECT 中(列级子查询)
SELECT hz.name ,(SELECT j.jname from jieji j WHERE hz.jiejiNum=j.jiejiNum) as '阶级名称' from hzuser hz;
关键词 / 符号 | 英文含义 | 语法作用 |
(SELECT j.jname ...) | 列级子查询 | 嵌套在 SELECT 列中的子查询,每行执行一次(关联当前行的hz.jiejiNum) |
整行含义:查询每个会员的姓名,并通过列级子查询匹配其对应的阶级名称(效果等价于多表连接,但效率较低,仅用于特殊场景)。
18. 分页查询(LIMIT 基础)
SELECT * from hzuser LIMIT 5;
关键词 / 符号 | 英文含义 | 语法作用 |
LIMIT | 限制 | 分页关键字,限制查询结果的行数 |
5 | 数字 | 表示仅返回前 5 行数据 |
整行含义:查询hzuser表的所有列,仅返回前 5 行数据。
19. 分页 + 排序(最高薪水前 3)
SELECT * from hzuser ORDER BY userSal DESC LIMIT 3;
关键词 / 符号 | 英文含义 | 语法作用 |
ORDER BY | 按… 排序 | 排序关键字,指定排序的列和规则 |
DESC | 降序(descending) | 排序方式(升序 ASC,默认可省略;降序 DESC) |
LIMIT 3 | 限制 3 行 | 排序后仅返回前 3 行(最高薪水的 3 个会员) |
整行含义:将hzuser表按薪水降序排列,返回前 3 行(薪水最高的 3 个会员)。
20. 分页(LIMIT m,n 语法)
SELECT * from hzuser LIMIT 0,3; -- 第一页 3条
SELECT * from hzuser LIMIT 3,3; -- 第二页 3条
SELECT * from hzuser LIMIT 6,3; -- 第三页 3条
关键词 / 符号 | 英文含义 | 语法作用 |
LIMIT m,n | 限制(起始索引,条数) | m = 起始索引(从 0 开始),n = 返回条数;索引 =(页数 - 1)* 条数 |
0,3 | 索引 0,3 条 | 第一页:索引从 0 开始,返回 3 条(第 1-3 行) |
3,3 | 索引 3,3 条 | 第二页:索引从 3 开始,返回 3 条(第 4-6 行) |
6,3 | 索引 6,3 条 | 第三页:索引从 6 开始,返回 3 条(第 7-9 行) |
整行含义:
- 第一行:查询hzuser表,从第 0 行(第一条)开始,返回 3 条数据(第一页);
- 第二行:从第 3 行开始,返回 3 条数据(第二页);
- 第三行:从第 6 行开始,返回 3 条数据(第三页)。
三、核心语法总结
- 多表查询:
- WHERE 方式:SELECT * FROM 表1,表2 WHERE 表1.字段=表2.字段(笛卡尔积 + 过滤);
- JOIN ON 方式:SELECT * FROM 表1 JOIN 表2 ON 连接条件 WHERE 筛选条件(语义更优);
- 自连接:将一张表虚拟为两张表,通过表1.字段=表2.字段关联(如下属 - 领导)。
- 子查询:
- 条件子查询:WHERE 字段 IN/=/>(子查询);
- 派生表:FROM (子查询) as 别名;
- 列级子查询:SELECT 字段,(子查询) as 别名 FROM 表(效率低,慎用)。
- 分页:
- LIMIT n:返回前 n 行;
- LIMIT m,n:m = 起始索引(从 0 开始),n = 条数;索引 =(页数 - 1)* 条数。
- 关键函数 / 运算符:
- 聚合函数:max()(最大值)、avg()(平均值);
- 去重:DISTINCT;
- 空值判断:IS NULL/IS NOT NULL;
- 排序:ORDER BY 字段 ASC/DESC。