【MySQL】--- 复合查询 内外连接

news2025/7/19 20:04:13

 Welcome to 9ilk's Code World

       

(๑•́ ₃ •̀๑) 个人主页:       9ilk

(๑•́ ₃ •̀๑) 文章专栏:     MySQL  


🏠 基本查询回顾

假设有以下表结构:

  • 查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J

思路 :  用两个条件对员工表进行筛选。条件1:工资高于500或岗位为MANAGER。条件2:姓名首字母为大写的J。条件1内为或关系,条件1和条件2为并联关系。

参考代码:

//like
select * from emp where (sal>500 or job='MANAGER') and ename like 'J%';
//子串
select * from emp where (sal>500 or job='MANAGER') and substring(ename,1,1)=='J'; //截取子串 

测试结果:

  • 按照部门号升序而雇员的工资降序排序

参考代码:

select * from emp order by deptno asc , sal desc; //asc升序 desc降序

测试结果:

  • 使用年薪进行降序排序

员工表中的comm奖金字段可以为空,但是MySQL中NULL是不参与运算的,我们可以使用ifnull函数进行处理。

参考代码:

//奖金可以为空有的岗位没奖金 所以对这种情况可以使用ifnull 是null就第二个参数
select *,sal*12+ifnull(comm,0) 年薪  from emp;

测试结果:

  • 显示工资最高的员工的名字和工作岗位

求最高可以使用排序也可以使用聚合函数。

参考代码:

select ename,job from emp order by sal desc limit 1;//排序
select ename, job from emp where sal = (select max(sal) from emp); //聚合函数子查询

测试结果:

注:MySQL允许在一条SQL内部再执行select查询,称为子查询!

  • 显示工资高于平均工资的员工信息

思路:我们先需要知道员工表中所有员工的平均信息,然后在员工表中根据平均工资筛选员工信息。

参考代码:

select * from emp where sal > (select AVG(sal) from emp); //先聚合统计平均工资

测试结果:

  • 显示每个部门的平均工资和最高工资

参考代码:

select deptno,AVG(sal),max(sal) from emp group by deptno;
//先分组 再聚合

测试结果:

  • 显示平均工资低于2000的部门号和它的平均工资

思路“我们先根据部门进行分组,然后对每个组进行聚合取得平均工资,最后对分组之后的结果having进行筛选。

参考代码:

select deptno,AVG(sal)平均工资  from emp group by deptno having 平均工资 < 2000;

测试结果:

  • 显示每种岗位的雇员总数,平均工资

参考代码:

select AVG(sal) 平均工资, count(ename) from emp group by job;
select job,count(*), format(avg(sal),2) from emp group by job;

测试结果:

🏠 多表查询

实际开发中往往数据来自不同的表,所以需要多表查询。本节我们用一个简单的公司管理系统,有三张表emp,dept,salgrade来演示如何进行多表查询。

案例:

  • 显示雇员名、雇员工资以及所在部门的名字因为上面的数据来自EMP和DEPT表,因此要联合查询

分析:雇员名和雇员工资信息来自员工表,而所在部门名字的信息来自部门表,那我们需要两张表的数据进行组合。

多表查询本质:将多张表中数据进行穷举组合,多张表进行笛卡尔积。此时多张表变为单表,多表操作转化为对单表的操作!

多表笛卡尔积会有多种组合结果,但有的组合结果是没有意义的,所以只要emp表中的deptno = dept表中的deptno字段的记录,其他的都是没意义的。

参考代码:

select emp.ename,emp.sal,dept.dname from emp,dept where emp.deptno= dept.deptno;
//
select ename,sal,dname from emp,dept where emp.deptno= dept.deptno;

测试结果:

注:对于两张表中各自的特有字段在查询时,不需要指明所属哪张表,如果是共有字段则需要指明是哪一张表的,否则会发生冲突。

MySQL中一切皆表,组合之后的表也是表结构!也可以对该表结构的数据进行整合。

  • 显示部门号为10的部门名,员工名和工资

参考代码:

select emp.ename,dept.dname,sal from emp,dept where (emp.deptno=dept.deptno and emp.deptno=10);

测试结果:

  • 显示各个员工的姓名,工资,及工资级别

思路:工资级别以及工资信息在工资表里,因此我们需要多表查询。同时工资表中有工资等级所属的工资范围,我们可以根据范围来判断员工表中员工薪资所属等级。

参考代码:

select ename,sal,grade from emp,salgrade where sal between losal and hisal;

测试结果:

🏠 自连接

自连接是指在同一张表连接查询,也就是同一张表进行笛卡尔积。

可行性:

select * from salgrade,salgrade;

测试结果:

注:两张相同的表进行笛卡尔积,表名相同会造成冲突!我们需要对两张表进行重命名。

案例: 显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号--empno)

  • 方法1:使用子查询

思路:先用子查询获取工FORD的上级领导的编号,再通过编号筛选出领导的相关信息。

参考代码:

select ename,empno from emp where empno=(select mgr from emp where ename='FORD');

测试结果:

  • 方法2:使用多表查询

思路:两张相同表进行笛卡尔积,假设t1为单纯员工表,t2用来作为“查询上级表”,则我们可以根据t2的mgr找出t1中是xxx的上级的员工;然后再筛选出t2表中名字是FORD,最后筛选出t1表中所求上级的编号和姓名。

参考代码:

 select t1.empno,t1.ename from emp as t1,emp as t2 where t1.empno=t2.mgr and t2.ename='FORD';

测试结果:

注:from执顺序先于where,因此where可以使用表的重命名!

🏠 子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。

🎵 单行子查询

单行子查询:返回一行记录的查询。

  • 显示SMITH同一部门的员工

参考代码:

select * from emp where deptno=(select deptno from emp where ename='SMITH');

测试结果:

🎵 多行子查询

多行子查询:返回多行记录的子查询。

  • in关键字;查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的。

思路:我们可以根据子查询10号部门的工作岗位然后进一步筛选。

参考代码:

select ename,job,sal,deptno from emp where job in (select distinct job from emp where deptno=10) and deptno<>10;

测试结果:

如果还想知道上面条件对应的员工属于部门的名字呢?

此时我们可以用上面筛选出来的“表”再和部门表进行笛卡尔积,筛选出部门名字!

参考代码:

select ename,job,sal,dname from (select ename,job,sal,deptno from emp where job in (select distinct job from emp where deptno=10) and deptno<>10) as tmp,deptp,dept where tmp.deptno=dept.deptno;

测试结果:

注:一个SQL的查询结果也是一个表结构,MySQL一切皆表,不是物理上真实存在的表才能做笛卡尔积。同时子查询不仅能出现在where后,也能出现在from后!

  • all关键字;显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号。

all表示的是查询结果中最大的

测试代码:

select ename,sal,deptno from emp where sal > all(select sal from emp where deptno=30);
//也可以使用聚合函数MAX
select ename,sal,deptno from emp where sal > (select MAX(sal) from emp where deptno=30);

测试结果:

  • any关键字;显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)。

any表示的就是查询结果中的任意一个。

参考代码:

select ename,sal,deptno from emp where sal > any(select sal from emp where deptno=30);

测试代码:

🎵 多列子查询

单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询则是指查询返回多个列数据的子查询语句。

案例:查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人。

思路:我们需要根据两个列的字段(部门和岗位)进行筛选,然后根据筛选结果筛选出其他雇员的信息。

参考代码:

select * from emp where deptno=(select deptno from emp where ename='SMITH') and job=(select job from emp where ename='SMITH') and ename<>'SMITH';
//多列子查询
select * from emp where (deptno,job) = (select deptno,job from emp where ename='SMITH') and ename<>'SMITH';

测试结果:

注:使用多列子查询时,括号内的列顺序和数目要和子查询的列顺序和数目匹配!

总结:目前全部的子查询都在where子句中,充当判断条件!但其实任何时刻,查询出来的结构,本质在逻辑上也是表结构

🎵 from子句中使用子查询

子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。

  • 显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资

思路:先找出每个部门的平均工资(分组),再根据这个子表和原表进行笛卡尔积,筛选出原表工资大于子表平均工资并且部门号不冲突的

参考代码:

//
select ename, deptno, sal, format(asal,2) from emp, (select avg(sal) asal, deptno dt from emp  group by deptno) tmp where emp.sal > tmp.asal and emp.detnnoptno=tmp.dt;
//
select emp.ename,emp.deptno,emp.sal,tmp.asal from (select AVG(sal) asal,deptno from emp group by deptno) as tmp,emp where (emp.sal > tmp.asal) and emp.depdeptno=tmp.deptno;

测试结果:

  • 查找每个部门工资最高的人的姓名、工资、部门、最高工资

思路:先找出每个部门的最高工资(分组),再根据这个子表和原表进行笛卡尔积,找出原表中工资等于子表中筛选出的每个部门的最高工资的&&满足两表部门号相同

参考代码:

select emp.deptno,emp.ename,emp.sal,tmp.msal from (select deptno,MAX(sal) msal from emp group by deptno) tmp,emp where tmp.msal = emp.sal and tmp.deptno=emp.deptno;

测试结果:

  • 显示每个部门的信息(部门名,编号,地址)和人员数量

(1)方法1:使用子查询

参考代码:

select dept.dname,dept.loc,dept.deptno,tmp.num from dept,(select deptno,count(*) num from emp group by deptno) tmp where dept.deptno = tmp.deptno;
//1.对EMP表进行人员统计
//2.将上面的表看作临时表

测试结果:

(2)使用多表

参考代码:

select emp.deptno,count(*),dept.dname,dept.loc from emp,dept where emp.deptno=dept.deptno group by emp.deptno,dept.loc,dept.dname;

测试结果:

总结:解决多表问题的本质:首先是先想办法把多表转化为单表,所以MySQL中所有select的问题全部都可以转化为单表问题!

🎵 合并查询

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all

1. union

该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行

案例:将工资大于2500或职位是MANAGER的人找出来

参考代码:

select ename,sal,job from emp where sal>2500 union select ename ,sal,job from emp where job='MANAGER';

测试结果:

2. union all

该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。

注:使用合并查询时列信息必须一样

🏠 表的内连接

内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,我们前面学习的查询都是内连接,也是在开发过程中使用的最多的连接查询。

语法

select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件;

注:前面学习的都是内连接。

案例:显示SMITH的名字和部门名称

1. where

-- 用前面的写法
select ename, dname from EMP, DEPT where EMP.deptno=DEPT.deptno and
ename='SMITH';

2. 标准内连接

-- 用标准的内连接写法
select ename, dname from EMP inner join DEPT on EMP.deptno=DEPT.deptno and
ename='SMITH';

🏠 表的外连接

外连接分为左外连接和右外连接

🎵 左外连接

如果联合查询,左侧的表完全显示我们就说是左外连接

案例

-- 建两张表
create table stu (id int, name varchar(30)); -- 学生表
insert into stu values(1,'jack'),(2,'tom'),(3,'kity'),(4,'nono');
create table exam (id int, grade int); -- 成绩表
insert into exam values(1, 56),(2,76),(11, 8);
  • 查询所有学生的成绩,如果这个学生没有成绩,也要将学生的个人信息显示出来

参考代码:

-- 当左边表和右边表没有匹配时,也会显示左边表的数据
select * from stu left join exam on stu.id=exam.id;

测试结果:

此时左表中每一个id都会显示,即使在右表没找到相同的id。

🎵 右外连接

如果联合查询,右侧的表完全显示我们就说是右外连接

语法:

select 字段 from 表名1 right join 表名2 on 连接条件;

案例

  • 对stu表和exam表联合查询,把所有的成绩都显示出来,即使这个成绩没有学生与它对应,也要显示出来。

参考代码:

select * from stu right join exam on stu.id=exam.id;

测试结果:

  • 列出部门名称和这些部门的员工信息,同时列出没有员工的部门

1.  方法一:左外连接

select d.dname, e.* from dept d left join emp e on d.deptno=e.deptno;

2. 方法二:右外连接

select d.dname, e.* from emp e right join dept d on d.deptno=e.deptno;

测试结果:


完。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2284395.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

书生大模型实战营2

L0——入门岛 Python基础 Conda虚拟环境 虚拟环境是Python开发中不可或缺的一部分&#xff0c;它允许你在不同的项目中使用不同版本的库&#xff0c;避免依赖冲突。Conda是一个强大的包管理器和环境管理器。 创建新环境 首先&#xff0c;确保你已经安装了Anaconda或Minico…

HTML5+SVG+CSS3实现雪中点亮的圣诞树动画效果源码

源码介绍 这是一款基于HTML5SVGCSS3实现雪中点亮的圣诞树动画效果源码。画面中的圣诞树矗立在雪地中&#xff0c;天上飘落着雪花。当鼠标滑过圣诞树时&#xff0c;可见到圣诞树上的灯光闪烁&#xff0c;同时左下角探出雪怪模样的半个脑袋&#xff0c;四处张望着。整体画面栩栩…

产业园管理系统提升企业综合管理效率与智能化水平的成功案例分析

内容概要 在当前科技迅猛发展的时代&#xff0c;越来越多的企业意识到数字化转型的重要性。为了提升管理效率和智能化水平&#xff0c;产业园管理系统应运而生&#xff0c;成为众多园区和商办写字楼不可或缺的一部分。无论是工业园、物流园还是公寓&#xff0c;这些系统都能为…

LeetCode - #195 Swift 实现打印文件中的第十行

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

强化学习数学原理(三)——值迭代

一、值迭代过程 上面是贝尔曼最优公式&#xff0c;之前我们说过&#xff0c;f(v)v&#xff0c;贝尔曼公式是满足contraction mapping theorem的&#xff0c;能够求解除它最优的策略和最优的state value&#xff0c;我们需要通过一个最优v*&#xff0c;这个v*来计算状态pi*&…

DeepSeek-R1:强化学习驱动的推理模型

1月20日晚&#xff0c;DeepSeek正式发布了全新的推理模型DeepSeek-R1&#xff0c;引起了人工智能领域的广泛关注。该模型在数学、代码生成等高复杂度任务上表现出色&#xff0c;性能对标OpenAI的o1正式版。同时&#xff0c;DeepSeek宣布将DeepSeek-R1以及相关技术报告全面开源。…

scratch变魔术 2024年12月scratch三级真题 中国电子学会 图形化编程 scratch三级真题和答案解析

目录 scratch变魔术 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、 推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、py…

MyBatis框架基础学习及入门案例(2)

目录 一、数据库建表(tb_user)以及添加数据。 &#xff08;1&#xff09;数据库与数据表说明。 &#xff08;2&#xff09;字段与数据说明。 二、创建模块(或工程)、导入对应所需依赖坐标。 三、编写MyBatis核心主配置文件。(解决JDBC中"硬编码"问题) &#xff08;1&…

python学opencv|读取图像(四十六)使用cv2.bitwise_or()函数实现图像按位或运算

【0】基础定义 按位与运算&#xff1a;全1取1&#xff0c;其余取0。按位或运算&#xff1a;全0取0&#xff0c;其余取1。 【1】引言 前序学习进程中&#xff0c;已经对图像按位与计算进行了详细探究&#xff0c;相关文章链接如下&#xff1a; python学opencv|读取图像&…

蓝桥杯省一

四个月从c&#xff0c;cpp&#xff0c;算法一起学到省一&#xff08;考研原因没参加国赛&#xff09; 有疑问可以关注私信哦 帖子后续也会持续更新&#xff0c;分享算法竞赛&#xff08;ccpc&#xff0c;天梯赛&#xff0c;蓝桥杯&#xff0c;浙大pta&#xff09;相关知识

C++ 新特性实现 ThreadPool

序言 在之前我们实现过线程池&#xff0c;但是非常基础。答题思路就是实现一个安全的队列&#xff0c;再通过 ThreadPool 来管理队列和线程&#xff0c;对外提供一个接口放入需要执行的函数&#xff0c;但是这个函数是无参无返回值的。  参数的问题我们可以使用 bind 来封装&a…

【数据结构】_以SLTPushBack(尾插)为例理解单链表的二级指针传参

目录 1. 第一版代码 2. 第二版代码 3. 第三版代码 前文已介绍无头单向不循环链表的实现&#xff0c;详见下文&#xff1a; 【数据结构】_不带头非循环单向链表-CSDN博客 但对于部分方法如尾插、头插、任意位置前插入、任意位置前删除的相关实现&#xff0c;其形参均采用了…

本地Harbor仓库搭建流程

Harbor仓库搭建流程 本文主要介绍如何搭建harbor仓库&#xff0c;推送本地镜像供其他机器拉取构建服务 harbor文档&#xff1a;Harbor 文档 | 配置 Harbor YML 文件 - Harbor 中文 github下载离线安装包 Releases goharbor/harbor 这是harbor的GitHub下载地址&#xff0c…

环境搭建--vscode

vscode官网下载合适版本 安装vscode插件 安装 MinGW 配置环境变量 把安装目录D&#xff1a;\mingw64 配置在用户的环境变量path里即可 选择用户环境变量path 点确定保存后开启cmd输入g&#xff0c;如提示no input files 则说明Mingw64 安装成功&#xff0c;如果提示g 不是内…

30289_SC65XX功能机MMI开发笔记(ums9117)

建立窗口步骤&#xff1a; 引入图片资源 放入图片 然后跑make pprj new job8 可能会有bug,宏定义 还会有开关灯报错&#xff0c;看命令行注释掉 接着把ture改成false 然后命令行new一遍&#xff0c;编译一遍没报错后 把编译器的win文件删掉&#xff0c; 再跑一遍虚拟机命令行…

IDEA工具下载、配置和Tomcat配置

1. IDEA工具下载、配置 1.1. IDEA工具下载 1.1.1. 下载方式一 官方地址下载 1.1.2. 下载方式二 官方地址下载&#xff1a;https://www.jetbrains.com/idea/ 1.1.3. 注册账户 官网地址&#xff1a;https://account.jetbrains.com/login 1.1.4. JetBrains官方账号注册…

【10.2】队列-设计循环队列

一、题目 设计你的循环队列实现。 循环队列是一种线性数据结构&#xff0c;其操作表现基于 FIFO&#xff08;先进先出&#xff09;原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。 循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普…

多人-多agent协同可能会挑战维纳的反馈

在多人-多Agent协同系统中&#xff0c;维纳的经典反馈机制将面临新的挑战&#xff0c;而协同过程中的“算计”&#xff08;策略性决策与协调&#xff09;成为实现高效协作的核心。 1、非线性与动态性 维纳的反馈理论&#xff08;尤其是在控制理论中&#xff09;通常假设系统的动…

HarmonyOS简介:应用开发的机遇、挑战和趋势

问题 更多的智能设备并没有带来更好的全场景体验 连接步骤复杂数据难以互通生态无法共享能力难以协同 主要挑战 针对不同设备上的不同操作系统&#xff0c;重复开发&#xff0c;维护多套版本 多种语言栈&#xff0c;对人员技能要求高 多种开发框架&#xff0c;不同的编程…

Edge-TTS在广电系统中的语音合成技术的创新应用

Edge-TTS在广电系统中的语音合成技术的创新应用 作者&#xff1a;本人是一名县级融媒体中心的工程师&#xff0c;多年来一直坚持学习、提升自己。喜欢Python编程、人工智能、网络安全等多领域的技术。 摘要 随着人工智能技术的快速发展&#xff0c;文字转语音&#xff08;Te…