MySQL联合查询(多表查询)

MySQL联合查询(多表查询)知识点总结

范式设计后数据拆分到多张表,想要拿到完整业务数据就需要联合查询,包含:内连接、外连接、自连接、子查询、合并查询、插入查询结果。

一、联合查询底层原理:笛卡尔积

  1. 多表查询会先做笛卡尔积,把A表每一行和B表每一行全部组合,生成巨大临时结果集。
  2. 再通过连接条件过滤无效组合,留下符合关联关系的数据。
  3. ⚠️注意:参与表越多、数据量越大,笛卡尔积结果集会爆炸,性能变差,尽量少关联过多表。

实操技巧:给表起别名简化书写;多表存在同名字段,必须使用表名.列名消除歧义。

测试用表说明

用到四张表:

  • student学生表、class班级表、course课程表、score成绩表。

二、表连接分类

1. 内连接 INNER JOIN

只返回两张表满足连接条件的记录 ,两边匹配不到的数据不会出现在结果。

两种等价写法:

sql 复制代码
-- 写法1:逗号 + where
select 字段 from 表1,表2 where 连接条件 and 其他条件;

-- 写法2:JOIN ... ON(推荐,连接条件和普通过滤条件分离)
select 字段 from 表1 inner join 表2 on 连接条件 where 其他条件;

示例:查询唐三藏所有考试成绩;多表联查学生+班级+课程+成绩;内连接不会出现没有成绩的学生。

2. 外连接

MySQL支持左外连接、右外连接,不支持全外连接

类型 说明 语法
左外连接 LEFT JOIN 保留左表全部行 ,右表匹配不到填充NULL select * from A left join B on 连接条件;
右外连接 RIGHT JOIN 保留右表全部行 ,左表匹配不到填充NULL select * from A right join B on 连接条件;

典型案例:

  1. 左连接:查询没有参加考试的学生 ,学生左表,成绩右表;判断成绩字段IS NULL筛选无成绩学生。
  2. 右连接:查询没有学生的班级,班级放join右侧,学生放左侧,学生字段为NULL即为空班级。

小技巧:左连接可以改写为右连接,开发优先习惯用左连接。

⚠️外连接关联条件写在ON后,不要写在WHERE,写where会退化成内连接。

3. 自连接

一张表自己和自己做连接 ,必须给同一张表起两个不同别名 ,否则报错。

用途:实现行与行之间对比 。

示例:同一个学生,比较MySQL课程成绩和Java课程成绩,把score表起两个别名s1、s2做关联。

三、子查询(嵌套查询)

子查询:将一条select的查询结果,当做另一条SQL的条件/临时表。分为四类:

  1. 单行子查询 :子查询返回1行结果,使用=判断。

    sql 复制代码
    select * from student where class_id = (select class_id from student where name='不想毕业');
  2. 多行子查询 :子查询返回多条,使用IN / NOT IN

    sql 复制代码
    select * from score where course_id in (select id from course where name='Java' or name='MySQL');
  3. 多列子查询 :子查询返回多列,外层where括号内写多列匹配 (col1,col2) IN (...),适合查找重复记录。

  4. FROM后的子查询(派生表/临时表) :把子查询结果当成一张临时表,必须给临时表起别名。

sql 复制代码
select * from score s, (子查询SQL) tmp where s.score > tmp.score;

注意:子查询可以多层嵌套,复杂SQL可读性变差,复杂场景优先改用表连接。

四、合并查询 UNION / UNION ALL

把多条SELECT结果集上下拼接 ,要求前后select返回列数量、类型一致,列名以第一条select为准。

  1. UNION:合并并且自动去重,消耗性能;
  2. UNION ALL:直接拼接,不去重,保留全部数据,性能更高;

业务如果不需要去重优先用UNION ALL。

示例:学生表id<3的数据 union 另一张student1全部数据。

五、插入查询结果

语法:INSERT INTO 目标表(列...) SELECT ...

把select查询出来的结果,直接插入目标表,常用于数据复制、迁移。

sql 复制代码
insert into student1(name,sno,age,gender,enroll_date,class_id) 
select s.name, s.sno, s.age, s.gender, s.enroll_date, s.class_id
from student s join class c on s.class_id=c.id where c.name='C++001班';

六、核心易错点整理

  1. 笛卡尔积风险:多表必须写连接条件,忘记条件会产生海量无效数据;
  2. 字段重名:多表同名字段必须加表别名限定,否则报Column ... is ambiguous;
  3. 外连接:匹配条件写ON,业务过滤写WHERE,不要把外连接匹配条件挪到where;
  4. from后面的子查询,临时表必须写别名,语法强制;
  5. UNION和UNION ALL区别:UNION自动去重,性能差;UNION ALL直接拼接;
  6. 自连接:同一张表做连接,必须设置两个不同别名;
  7. IN子查询注意NULL:子查询结果存在NULL时,NOT IN查询结果为空,尽量避免。
相关推荐
+VX:Fegn089542 分钟前
计算机毕业设计|基于springboot + vue外卖点餐系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
FYKJ_20101 小时前
springboot刑事案件管理系统03047-计算机课程设计、毕业设计
vue.js·spring boot·python·mysql·typescript·spark·django
盟接之桥2 小时前
线束数字化--先进先出为什么总是停留在纸面上?
大数据·网络·数据库·人工智能·制造·ai编程
FYKJ_20102 小时前
springboot助农产品销售商城05829-计算机课程设计、毕业设计
java·spring boot·python·mysql·spark·django
Kamille Bidan2 小时前
MySQL数据库引擎介绍
mysql
adinnet20263 小时前
预算管控:预算执行与偏差问数
大数据·数据库
Omics Pro4 小时前
Cell封面|衰老生物学开源AI工具包
数据库·人工智能·算法·机器学习·自然语言处理
FYKJ_20105 小时前
springboot雅集社区养老管理系统04456-计算机课程设计、毕业设计
vue.js·spring boot·python·mysql·typescript·spark·django
FYKJ_20105 小时前
express皖美特色农产品网售系统53118-计算机课程设计、毕业设计
javascript·vue.js·spring boot·mysql·typescript·spark·express
FYKJ_20106 小时前
springboot羽毛球场地管理系统00626-计算机课程设计、毕业设计
vue.js·spring boot·python·mysql·typescript·spark·django