当前位置: 首页 > news >正文

05MySQL多表查询全解析

mysql的多表查询

概述:

项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种:
1:一对多(多对一)
2:多对多
3:一对一

多表查询-笛卡尔积

 笛卡尔积:笛卡尔乘积是指在数学中,两个集合A集合和B集合的所有组合情况。(在多表查询时,需要消除无效的笛卡尔积)

-- 笛卡尔查询,不过滤无用信息
SELECT * FROM emp,dept;-- 内连接查询,可以过滤无用信息
SELECT * FROM emp,dept where emp.dept_id = dept.id order by emp.id asc;

多表查询-内连接查询

内连接查询的是两张表交集的部分

语法:

隐式内连接:

SELECT 字段列表 FROM 表1,表2 WHERE 条件…;

显示内连接:

SELECT 字段列表 FROM 表1 [INNER] JOIN 表2 ON 连接条件…;

-- 隐式内连接
SELECT e.name,d.name
FROM emp e,dept d
WHERE e.dept_id=d.id;-- 显示内连接
SELECT e.name,d.name
FROM emp e
INNER JOIN dept d
ON e.dept_id=d.id;

在实际开发中,推荐使用显式内连接的写法,尤其是在多表连接时,INNER JOIN的语法能更清晰地体现表之间的关系,使代码更易读、易维护。

多表查询-外连接查询

语法:

左外连接查询

SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 条件...;

返回表1的所有记录,以及表2与表1满足连接条件的记录

右外连接查询

SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 条件...;

返回表2的所有记录,以及表1与表2满足连接条件的记录

左右外连接常用于需要完整保留主表数据并关联从表信息的场景

-- 外连接演示
-- 查询emp表的所有数据,和对应的部门信息(左外连接)
SELECT e.*,d.name AS d_name
FROM emp e
LEFT OUTER JOIN dept d
ON e.dept_id=d.id;-- 查询dept表的所有数据,和对应的员工信息(右外连接)
SELECT d.*,e.*
FROM emp e
RIGHT OUTER JOIN dept d
ON e.dept_id=d.id;

多表查询-自连接查询

自连接查询是 SQL 中一种特殊的多表查询方式,它指的是同一张表与自身进行连接,通常用于处理表中存在层级关系或自引用关系的数据。

例如,在员工表中,可能有一个 manager_id 字段指向该员工的上级领导(也是员工表中的一条记录),这时就可以通过自连接查询员工与其上级的信息。

自连接查询,可以是内连接查询,也可以是外连接查询。

自连接的内连接查询:

SELECT 字段列表 FROM  表A 别名a,表A 别名b  WHERE  条件语句;

自连接的外连接查询:

SELECT 字段列表 FROM 表A 别名a [左/右] JOIN 表A 别名b  ON 条件语句;

-- 1. 查询员工	及其	所属领导的名字
SELECT a.name '员工',b.name '上司' FROM emp a,emp b WHERE a.managerid=b.id; -- 2. 查询所有员工 emp 及其领导的名字 emp,如果员工没有领导,也需要查询出来
SELECT a.name '员工',b.name '上司' FROM emp a left join emp b ON a.managerid=b.id;

多表查询-联合查询

对于 union查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。

联合查询语法:

SELECT 字段列表 FROM 表A ...
UNION [ALL]
SELECT 字段列表 FROM 表B ...;

如果添加all参数,则会显示重复的记录,不添加就是去重

-- 1.将薪资低于5000的员工,和年龄大于50岁的员工全部查询出来。
SELECT * FROM emp WHERE age >50
union 
SELECT * FROM emp WHERE salary < 5000;

多表查询-子查询

子查询:

概念:SQL语句中嵌套SELECT语句,称为嵌套查询,又称子查询。

SELECT  *  FROM  t1  WHERE  column1=(SELECT  column1  FROM  t2);
子查询外部的语句可以是INSERT/UPDATE/DELETE/SELECT的任何一个。

根据子查询结果不同,分为:

1标量子查询(子查询结果为单个值)
2列子查询(子查询结果为一列)
3行子查询(子查询结果为一行)
4表子查询(子查询结果为多行多列)

根据子查询位置,分为:WHERE之后、FROM之后、SELECT之后。

标量子查询

子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询成为标量子查询。            常用的操作符:  =   <>   >   >=   <   <=

-- 标量子查询-- 1.查询“销售部”的所有员工信息
-- a.查询“销售部”部门ID
-- b.根据销售部部门ID,查询员工信息
SELECT * 
FROM emp 
WHERE dept_id=(SELECT id FROM dept WHERE name='销售部');-- 2.查询在“方东白”入职之后的员工信息
-- a.查询方东白的入职日期
-- b.查询指定入职日期之后入职的员工信息
SELECT * 
FROM emp 
WHERE entrydate >= (SELECT entrydate FROM emp WHERE name='方东白');

列子查询

子查询返回的结果是一列(可以是多行),这种子查询称为列子查询。

常用的操作符:IN、NOT IN、ANY、SOME、ALL

IN   判断字段是否在这些值中,如果符合则返回        
NOT  IN与IN相反
ANY满足任意一个则返回
SOME完全等于any
ALL必须所有值都满足才返回
-- 列子查询
-- 1.查询“销售部”和“市场部”的所有员工信息
-- a.查询“销售部”和“市场部”的部门ID
SELECT id FROM dept WHERE name = '销售部' OR name = '市场部';
-- b.根据部门ID,查询员工信息
SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE name = '销售部' OR name = '市场部');
SELECT * FROM emp WHERE dept_id NOt IN (2,4,6);
-- 2.查询比财务部所有人工资都高的员工信息
-- a.查询所有财务部人员工资
SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '财务部');
-- b.比财务部所有人工资都高的员工信息
SELECT * FROM emp WHERE salary > ALL (SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '财务部'));-- 3.查询比研发部其中任意一人工资高的员工信息
-- a.查询研发部所有人工资
SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '研发部');
-- b.比研发部其中任意一人工资高的员工信息
SELECT * FROM emp WHERE salary > ANY (SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '研发部'));
SELECT * FROM emp WHERE salary > SO(SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '研发部'));

行子查询

子查询返回的结果是一行(可以是多列),这种子查询称为行子查询。

常用的操作符:=、<>、IN、NOT IN

-- 行子查询
-- 1.查询与“张无忌”的薪资及直属领导相同的员工信息;
-- a.查询“张无忌”的薪资及直属领导
SELECT salary,managerid FROM emp WHERE name ='张无忌';
--  b.查询与“张无忌”的薪资及直属领导相同的员工信息;
SELECT * FROM emp WHERE (salary,managerid) = (12500,1);
SELECT * FROM emp WHERE (salary,managerid) = (SELECT salary,managerid FROM emp WHERE name ='张无忌');

表子查询

子查询返回的结果是多行多列,这种子查询称为表子查询。

可以这样简单理解,但更准确地说,表子查询(Table Subquery)是指子查询返回的结果是一个多行多列的数据集(类似一张 “临时表”),主查询会基于这个 “临时表” 来进行进一步的查询操作(比如关联查询、IN 匹配等)。

-- 表子查询-- 1.查询与“鹿杖客”,“宋远桥”的职位和薪资相同的员工信息
-- a.查询“鹿杖客”,“宋远桥”的职位和薪资
SELECT salary,job FROM emp WHERE name= '鹿杖客' OR name= '宋远桥';
-- b.查询与“鹿杖客”,“宋远桥”的职位和薪资相同的员工信息
SELECT * FROM emp WHERE (salary,job) IN (SELECT salary,job FROM emp WHERE name= '鹿杖客' OR name= '宋远桥');-- 2.查询入职日期是"2006-01-01"之后的员工信息,及其部门信息
-- a.入职日期是"2006-01-01"之后的员工信息
SELECT * FROM emp WHERE entrydate > '2006-01-01';
-- b.查询这部分员工,对应的部门信息;
SELECT e.*,d.* FROM (SELECT * FROM emp WHERE entrydate > '2006-01-01') e left join dept d ON e.dept_id=d.id;

多表查询--综合练习

-- 1.查询员工的姓名、年龄、职位、部门信息(隐式内连接)
SELECT e.name,e.age,e.job,d.name
FROM emp e,dept d
WHERE e.dept_id=d.id;-- 2.查询年龄小于30岁的员工的姓名、年龄、职位、部门信息(显式内连接)
SELECT e.name,e.age,e.job,d.name
FROM emp e
INNER JOIN dept d
ON e.dept_id=d.id
WHERE e.age < 30;-- 3.查询拥有员工的部门ID、部门名称
SELECT DISTINCT  d.id,d.name
FROM emp e,dept d
WHERE e.dept_id=d.id;-- 4.查询所有年龄大于40岁的员工,及其归属的部门名称;如果员工没有分配部门,也需要展示出来
SELECT e.*,d.name
FROM emp e
LEFT OUTER JOIN dept d
ON e.dept_id=d.id
WHERE e.age > 40;-- 5.查询所有员工的工资等级
SELECT e.*,s.grade
FROM emp e,salgrade s
WHERE e.salary BETWEEN s.losal AND s.hisal;-- 6.查询“研发部”所有员工的信息及工资等级
SELECT e.*,d.name,s.grade
FROM emp e,dept d, salgrade s
WHERE e.dept_id=d.id
AND d.name = '研发部'
AND e.salary BETWEEN s.losal AND s.hisal;-- 7.查询“研发部”员工的平均工资
SELECT avg(e.salary)
FROM emp e,dept d
WHERE d.name= '研发部' AND e.dept_id=d.id-- 8.查询工资比“灭绝”高的员工信息。
SELECT e.*
FROM emp e
WHERE salary > (SELECT salary FROM emp e WHERE name='灭绝')-- 9.查询比平均薪资高的员工信息
SELECT * 
FROM emp 
WHERE salary > (SELECT avg(salary) FROM emp  );-- 10.查询低于本部门平均工资的员工信息
SELECT e2.* FROM emp e2 
WHERE salary < (SELECT avg(salary) FROM emp e1 WHERE e1.dept_id=e2.dept_id);-- 11.查询所有的部门信息,并统计部门的员工人数
SELECT d.id,d.name,(SELECT count(*) FROM emp e WHERE e.dept_id=d.id) FROM dept d;

这是我的个人学习笔记,主要用于记录自己对知识点的理解和梳理。由于目前仍在学习探索阶段,内容中难免存在理解偏差或表述疏漏,恳请各位大佬不吝赐教,多提宝贵意见~ 若有不同看法,欢迎理性交流探讨,感谢包容与指正!

http://www.dtcms.com/a/358373.html

相关文章:

  • Flutter 跨平台开发环境搭建指南
  • Spring Boot 后端接收多个文件的方法
  • Android 权限申请现代化指南
  • 机器学习中的欠拟合与过拟合
  • SC税务 登录滑块 分析
  • 桌面GIS软件FlatGeobuf转Shapefile代码分享
  • Coze源码分析-API授权-添加新令牌-后端源码
  • 项目管理常用的方法有哪些
  • 国标调查:引领汽车消费市场健康发展的理性指南
  • 第2节:项目前期准备
  • Raycast 使用指南:解锁 macOS 生产力新高度
  • opencv实现轮廓绘制和选择
  • Intellij IDEA社区版(下载安装)
  • 学习python第15天
  • 网络编程(4)
  • 项目管理方法全流程解析
  • 【前端教程】HTML 基础界面开发
  • destoon8.0根据模块生成html地图
  • 星链调查(SOS)线上问卷调查服务:全流程专业闭环
  • Python自定义函数形式参中的*args、**kwargs、*和/
  • 学习:uniapp全栈微信小程序vue3后台(7)
  • AI生成思维导图和AI生成Excel公式
  • Dify1.8.0最新版本安装教程:Ubuntu25.04系统本地化安装部署Dify详细教程
  • Langflow核心技术学习笔记
  • kube-proxy
  • 【系列09】端侧AI:构建与部署高效的本地化AI模型 第8章:移动端部署实战 - Android
  • 宽带有丢包,重传高的情况怎么优化
  • w嵌入式分享合集125
  • day43-Ansible-PlayBook
  • web渗透PHP反序列化漏洞