mysql-实战案例 (超详细版)

 🎉欢迎您来到我的MySQL基础复习专栏

☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹
✨博客主页:小小恶斯法克的博客
🎈该系列文章专栏:重拾MySQL
🍹文章作者技术和水平很有限,如果文中出现错误,希望大家能指正🙏
📜 感谢大家的关注! ❤️

目录

🚀​​​​​​多表查询综合案例

✨查询员工的姓名、年龄、职位、部门信息 (隐式内连接,需要消除笛卡尔积)

✨查询年龄小于30岁的员工的姓名、年龄、职位、部门信息(显式内连接)

✨查询拥有员工的部门ID、部门名称 (难点在于有一个部门是没有员工的)

✨查询所有年龄大于40岁的员工, 及其归属的部门名称; 如果员工没有分配部门, 也需要展示出来(因为没有部门的也要展示,只能使用外连接,外连接大部分采用左外,因为右外也可以通过调换表顺序改为左外)

✨查询所有员工的工资等级 (发现跟部门没有关系,而员工表中只有工资,没有等级,所以涉及新表salgrade)

✨查询 "研发部" 所有员工的信息及工资等级

✨查询 "研发部" 员工的平均工资

✨查询工资比 "n" 高的员工信息。

✨查询比平均薪资高的员工信息

✨查询低于本部门平均工资的员工信息

✨查询所有的部门信息, 并统计部门的员工人数

✨查询所有学生的选课情况, 展示出学生名称, 学号, 课程名称


🚀​​​​​​多表查询综合案例

数据环境准备:

create table salgrade(
grade int, --薪资等级
losal int, --这个等级的最低薪资
hisal int --这个等级的最高薪资
) comment '薪资等级表'; insert into salgrade values (1,0,3000);
insert into salgrade values (2,3001,5000);
insert into salgrade values (3,5001,8000);
insert into salgrade values (4,8001,10000);
insert into salgrade values (5,10001,15000);
insert into salgrade values (6,15001,20000);
insert into salgrade values (7,20001,25000);
insert into salgrade values (8,25001,30000);

在这个案例中,我们主要运用上面所讲解的多表查询的语法,完成以下的12个需求即可,而这里主要涉  及到的表就三张:emp员工表、dept部门表、salgrade薪资等级表 。


✨查询员工的姓名、年龄、职位、部门信息 (隐式内连接,需要消除笛卡尔积)

表 : empcp , dept

连接条件: empcp.dept_id = dept.id

这里再重复一下,如果给表起了别名你就必须要用别名去定义字段了

select e.name , e.age , e.job , d.name from empcp e , dept d where e.dept_id = d.id;

 执行:


✨查询年龄小于30岁的员工的姓名、年龄、职位、部门信息(显式内连接)

表 : empcp , dept

连接条件: empcp.dept_id = dept.id

在DQL语句中我们的查询条件在哪个关键字之后?是在where之后

select e.name , e.age , e.job , d.name from empcp e inner join dept d on e.dept_id =d.id where e.age < 30;

执行:


✨查询拥有员工的部门ID、部门名称 (难点在于有一个部门是没有员工的)

表 : empcp , dept

连接条件: empcp.dept_id = dept.id

换个思路:我们要去查拥有员工的部门,其实就是查询部门表和员工表之间的交集,怎么去查询两个表之间的交集,其实就是用内连接

select  * from empcp e , dept d where e.dept_id = d.id ;

而我们只要返回部门id,和部门名称,所以把*改为d.id,d.name

发现重复,去重,用关键字distinct

select distinct d.id , d.name from empcp e , dept d where e.dept_id = d.id;

执行:


✨查询所有年龄大于40岁的员工, 及其归属的部门名称; 如果员工没有分配部门, 也需要展示出来(因为没有部门的也要展示,只能使用外连接,外连接大部分采用左外,因为右外也可以通过调换表顺序改为左外)

表 : empcp , dept

连接条件: empcp.dept_id = dept.id

select * from empcp e left join dept d on e.dept_id = d.id where e.age > 40;

然后把*换成员工表的所有字段e.*,和部门名称d.name,如下

select e.*, d.name from empcp e left join dept d on e.dept_id = d.id where e.age >40 ;

执行:


✨查询所有员工的工资等级 (发现跟部门没有关系,而员工表中只有工资,没有等级,所以涉及新表salgrade)

表 : empcp , salgrade

连接条件 : empcp.salary >= salgrade.losal and empcp.salary <= salgrade.hisal

1.empcp表与salgrade表进行联合查询

2.empcp表与salgrade之间有没有外键关联?没有,如果要说empcp和salgrade之间没有外键关联,怎么产生关系呢?它们之间产生关系实际上通过一个字段salary产生关系,我们要去判断员工薪资等级,就要让这个薪资介于最小值与最大值之间,这就是连接条件

select *  from empcp e,salgrade s where e.salary >= s.losal and e.salary <= s.hisal ;

再改细节,*变为empcp表的全部字段e*,和salgrade表中的grade字段s.grade

-- 方式一
select e.* , s.grade , s.losal, s.hisal from empcp e , salgrade s where e.salary >= s.losal and e.salary <= s.hisal;-- 方式二
select e.* , s.grade , s.losal, s.hisal from empcp e , salgrade s where e.salary between s.losal and s.hisal;

执行:


✨查询 "研发部" 所有员工的信息及工资等级

表 : empcp , salgrade , dept

连接条件 : empcp.salary between salgrade.losal and salgrade.hisal , empcp.dept_id = dept.id

查询条件 : dept.name = '研发部'

梳理:

1.因为员工表中只有部门的id,而这里要根据部门的名词去查,所以这个里面涉及的表结构将会是三张表

2.那么可想而知,三张表我们连接连接的条件会有几个?2个

3.联查n张表,至少需要n-1个条件

4.我们去梳理连接条件的时候,不要一股脑的梳理三张表的条件,两个两个去梳理

5.首先empcp和salgrade的连接条件我们已经梳理过了,就是empcp.salary between salgrade.losal and salgrade.hisal

6.再梳理第二个条件empcp表和dept表它们什么条件,不就是empcp.dept_id = dept.id

代码思路:

1.select * from empcp e , dept d , salgrade s ; 这种我们称之为隐式内连接

2.连接的条件将在where之后编写 

3.select * from empcp e , dept d , salgrade s where e.dept_id = d.id;

4.如果是多个连接条件之间使用and进行连接

5.select * from empcp e , dept d , salgrade s where e.dept_id = d.id and e.salary between s.losal and s.hisal;

6为了让语法更加清晰,可以用括号完善一下

7.select * from empcp e , dept d , salgrade s where e.dept_id = d.id and (e.salary between s.losal and s.hisal);

8.还有一个查询条件,记住如果说在连接查询中还有额外的查询条件,此时直接在where后继续跟着写就可以

9.select * from empcp e , dept d , salgrade s where e.dept_id = d.id and (e.salary between s.losal and s.hisal) and d.name = '研发部';

10.最后将*改动,写为需要取的字段e.*员工信息,s.grade工资等级,如下:

select e.* , s.grade from empcp e , dept d , salgrade s where e.dept_id = d.id and (
e.salary between s.losal and s.hisal ) and d.name = '研发部';我们可以格式化一下代码更清楚--
select e.*, s.grade
from empcp e,dept d,salgrade s
where e.dept_id = d.idand (e.salary between s.losal and s.hisal)and d.name = '研发部';

执行:


✨查询 "研发部" 员工的平均工资

表 : empcp , dept

连接条件  : empcp.dept_id = dept.id

要求平均数的聚合函数是avg

select * from empcp e , dept d where e.dept_id = d.id ; 

还有一个查询条件 查询研发部 d.name = "研发部"

select * from empcp e , dept d where e.dept_id = d.id and d.name = "研发部"

基本的sql编写完了再对*进行优化,如下

select avg(e.salary) from empcp e, dept d where e.dept_id = d.id and d.name = '研发部';

执行:


✨查询工资比 "n" 高的员工信息。

思路:

拆解为两步

1.查询 "n" 的薪资

select salary from empcp where name = 'n';

2.查询比她工资高的员工数据

select * from empcp where salary > ( select salary from empcp where name = 'n' );
--后面其实就是刚刚查出来的14000,这个14000就是上面那条语句查询返回的结果,所以我们要通过子查询来实现,把上面的语句放到下面,然后再加上括号

执行:

执行:


✨查询比平均薪资高的员工信息

思路:

拆解为两步

1.查询员工的平均薪资

select avg(salary) from empcp;

2.查询比平均薪资高的员工信息

select * from empcp where salary > ( select avg(salary) from empcp );

执行:

执行:


✨查询低于本部门平均工资的员工信息

思路:

拆解为两步

1.查询指定部门平均薪资

比如查询1号部门的平均薪资

select * from emp e1 where e1.dept_id = 1

*改avg(e1.salary) 此时只能用别名e1

select avg(e1.salary) from empcp e1 where e1.dept_id = 1;select avg(e1.salary) from empcp e1 where e1.dept_id = 2;

2.查询低于本部门平均工资的员工信息

思路:

1.首先查询出所有的员工数据

2.select * from empcp;

3.此时所有的员工数据都拿到了,在此基础上增加一个查询条件,salary<当前部门的平均薪资

4.当前部门的平均薪资,只需要把当前的部门薪资传递下来,也就是上面的那句sql语句

select * from empcp where salary < (select avg(e1.salary) from empcp e1 where e1.dept_id = 1);

5.但是里面写死的部门id我们要替换掉,比如当我们去判断第一行数据时,需要传递的部门id是5,去判断第二行数据时,需要传递的部门id是1

6.此时我们只需要把dept_id这个字段传进来即可,我们需要把empcp起一个别名e2

7.这里就应该是select * from empcp e2 where e2.salary < (select avg(e1.salary) from empcp e1 where e1.dept_id = 1);e2.salary < 当前部门的平均薪资,再把当前部门传进来

8.当前部门应该就是e2.dept_id,代码如下

select * from empcp e2 where e2.salary < ( select avg(e1.salary) from empcp e1 wheree1.dept_id = e2.dept_id );

执行:

执行:

为了验证查询到的字段,我们可以在*之后增加一个输出字段, 我们可以把子查询直接粘贴过来,这个不就是当前部门的平均薪资嘛,我们再取一个别名为”当前部门的平均薪资“

select e2.*, (select avg(e1.salary) from empcp e1 where e1.dept_id = e2.dept_id) '当前部门平均薪资'
from empcp e2
where e2.salary < (select avg(e1.salary) from empcp e1 where e1.dept_id = e2.dept_id);

 对比后发现,是正确的


✨查询所有的部门信息, 并统计部门的员工人数

1.先查询所有部门信息

2.select id,name from dept;

3.此时查出了所有的部门id,以及部门的名称

4.接着考虑如何统计部门的员工数量

5.select count(*) from empcp where dept_id = 1;

6.这条语句是统计1号部门的员工数量

7.接下来需要考虑,在上面的语句下如何统计1号部门的员工数量,2号部门的员工数量

8.我再添加一个查询id,此时select id,name,id '人数' from dept;

9.这个id本身不是查询人数,我想要后面的dept.id查询为人数,能不能根据id查询出人数呢?可以,就是这句,统计1号部门的员工数量select count(*) from empcp where dept_id = 1;

10.变为select id,name,(select count(*) from empcp where dept_id = id) '人数' from dept;  加上括号,变成一个子查询存在

11.这里面最需要注意的是标红的dept_id是empcp表的id,紫id是dept表的id

12.此时就要给表起对应的别名,给empcp起别名为e,给dept起名为d

13.select d.id, d.name,(select count(*) from empcp e where e.dept_id =d.id) '人数' from dept  d;

select d.id, d.name , ( select count(*) from empcp e where e.dept_id = d.id ) '人数' from dept d;

执行:


✨查询所有学生的选课情况, 展示出学生名称, 学号, 课程名称

表 : student , course , student_course

连接条件: student.id = student_course.studentid , course.id = student_course.courseid

1.之前讲解表与表之间的关系时,特别说明了学生和课程的关系是多对多的关系,一个学生可以选择多个课程,一个课程也可以供多个学生选择,涉及的表有三张

2.这三张表会通过中间表student_course来维护它们之间的关系

3.三张表在消除笛卡尔积的时候需要3-1个关系

4.先梳理一下连接条件

5.student.id = student_course.studentid,course.id = student_course.courseid

ps:第一张是student表,第二张是student_course表,第三张是course表

  

6.select * from student s,student_course sc,course c where s.id = sc.studentid and  c.id = sc.courseid ;

7.再对*优化

8.我们只需要展示学生的姓名, 学号,课程也就是s.name , s.no , c.name ,代码如下


select s.name , s.no , c.name from student s , student_course sc , course c where
s.id = sc.studentid and sc.courseid = c.id ;

执行:


总结:本篇博客到这里就结束了,希望能帮到你,谢谢你这么好看还来看我

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

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

相关文章

VL53L4CD TOF开发(1)----驱动TOF进行测距

VL53L4CX TOF开发.1--驱动TOF进行测距 概述视频教学样品申请完整代码下载主要特点硬件准备技术规格系统框图应用示意图生成STM32CUBEMX选择MCU串口配置IIC配置 XSHUTX-CUBE-TOF1演示结果 概述 VL53L4CD适用于接近测量和短距离测量&#xff0c;可实现从仅仅1 mm到1300 mm的超精…

SAP SD-DN-MM 交货单相关物料凭证的视图的日期问题

眼下有个需求 获取交货单对应的物料凭证的过账日期BLDAT。 同步BW数据过去 新增一个数据库视图 但是实际使用时&#xff0c;有效部分仅本月&#xff0c;再选择条件里面要加上 MATdoc-bldat > sy-datum - sydatum6(2). 于是使用ST05 跟踪了一下&#xff0c;发现在DD28S…

echarts——折线图实现不同区间不同颜色+下钻/回钻功能——技能提升

echarts——折线图实现不同区间不同颜色下钻/回钻功能——技能提升 需求场景解决步骤1&#xff1a;安装echarts插件解决步骤2&#xff1a;html代码解决步骤3&#xff1a;封装option配置和initChart渲染方法解决步骤4&#xff1a;回钻功能 需求场景 最近在写后台管理系统时&…

乐意购项目前端开发 #2

一、Axios的安装和简单封装 安装Axios npm install axios在utils目录下创建 http.js 文件, 内容如下 import axios from axios// 创建axios实例 const http axios.create({baseURL: http://localhost:9999,//后端服务器地址timeout: 5000 })// axios请求拦截器 http.interc…

为什么使用双token实现无感刷新用户认证?

单token机制 认证机制&#xff1a;对与单token的认证机制在我们项目中仅使用一个Access Token的访问令牌进行用户身份认证和授权的方案处理。 不足之处&#xff1a; 安全性较低&#xff08;因为只有一个token在客户端和服务器端之间进行传递&#xff0c;一旦Access Token被截…

pip查看某个包存在的历史版本

简介&#xff1a;当我们想查看某个包有哪些可安装版本&#xff0c;但是又不想去官网查询&#xff0c;如何用pip命令查询出全部历史版本&#xff1f; 历史版本&#xff1a; Python&#xff1a;pip升级超时解决方案 Python&#xff1a;指定的Python版本pip Python&#xff1a…

鸿蒙开发-UI-布局

鸿蒙开发-序言 鸿蒙开发-工具 鸿蒙开发-初体验 鸿蒙开发-运行机制 鸿蒙开发-运行机制-Stage模型 鸿蒙开发-UI 鸿蒙开发-UI-组件 鸿蒙开发-UI-组件-状态管理 鸿蒙开发-UI-应用-状态管理 鸿蒙开发-UI-渲染控制 文章目录 前言 一、布局概述 1.布局结构 2.布局元素组成 3.布局分类 …

TRB 2024论文分享:基于生成对抗网络和Transformer模型的交通事件检测混合模型

TRB&#xff08;Transportation Research Board&#xff0c;美国交通研究委员会&#xff0c;简称TRB&#xff09;会议是交通研究领域知名度最高学术会议之一&#xff0c;近年来的参会人数已经超过了2万名&#xff0c;是参与人数和国家最多的学术盛会。TRB会议几乎涵盖了交通领域…

三、ngxin虚拟主机

目录 什么是nginx虚拟主机修改端口 访问页面1、配置nginx.config 文件2、 添加配置给目录中写入内容检测nginx 是否有语法错误&#xff08;nginx -t&#xff09;重启 nginx查看配置结果 不同主机网卡 查看到不同的页面先添加一个临时ip修改ngixn配置文件创建目录文件检测nginx …

React入门 - 06(TodoList 列表数据的新增和删除)

本章内容 目录 一、实践一下 React 的列表渲染二、TodoList 新增功能三、列表循环的 key四、删除 上一节内容我们完成了输入框中可以自由输入内容&#xff0c;这一节我们继续 TodoList功能的完善&#xff1a;列表数据的新增和删除。 在开始之前&#xff0c;我们先介绍一下 Re…

前端对接电子秤、扫码枪设备serialPort 串口使用教程

因为最近工作项目中用到了电子秤&#xff0c;需要对接电子秤设备。以前也没有对接过这种设备&#xff0c;当时也是一脸懵逼&#xff0c;脑袋空空。后来就去网上搜了一下前端怎么对接&#xff0c;然后就发现了SerialPort串口。 Serialport 官网地址&#xff1a;https://serialpo…

Linux 内核学习 3 - 虚拟内存和物理内存

虚拟内存其实是 CPU 和操作系统使用的一个障眼法&#xff0c;联手给进程编织了一个假象&#xff0c;让进程误以为自己独占了全部的内存空间&#xff1a; 在 32 位系统中&#xff0c;进程以为自己独占了 3G 的内存空间。 在 64 位系统中&#xff0c;进程以为自己独占了 128T 的…

杨中科 EFCORE 第四部分 命令详解56-61

Migrations 深入研究Migrations 1、使用迁移脚本&#xff0c;可以对当前连接的数据库执行编号更高的迁移&#xff0c;这个操作叫做“向上迁移” (Up)&#xff0c;也可以执行把数据库回退到旧的迁移&#xff0c;这个操作叫“向下迁移(Down&#xff09; 2、除非有特殊需要&…

机器人行业概况(2)

上篇已经介绍过关于机器人的定义以及分类&#xff0c;下面来看看机器人产业市场规模。 二、国内机器人产业市场规模 中国机器人产业在国家智能制造相关政策的引导下蓬勃发展。在新冠肺炎疫情防控期间&#xff0c;消毒、配送、测温、巡检等各类机器人的“火线上岗”&#xff0…

spring-boot2.7.8添加swagger

一、新建项目swaggerdemo 二、修改pom.xml 注意修改&#xff1a;spring-boot-starter-parent版本为&#xff1a;2.7.8 添加依赖&#xff1a; springfox-swagger2 springfox-swagger-ui springfox-boot-starter <?xml version"1.0" encoding"UTF-8"…

QT第3天

如上图界面&#xff0c;需求如下&#xff1a; 1、根据名字添加水果&#xff0c;并设置好单价 2、切换文件查看模式 3、点击任意水果可以显示单价 4、重量改变时&#xff0c;总价自动显示 //widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <Q…

RH850P1X芯片学习笔记-Flash Memory

文章目录 FeaturesClock Supply Block DiagramFlash SizeMemory ConfigurationRegistersRegister Base AddressList of RegistersRegister Reset Condition 与Flash Memory相关的操作模式Functional OverviewOption BytesOPBT0 — Option Byte 0OPBT1 — Option Byte 1OPBT2 —…

【CSS】保持元素宽高比

保持元素的宽高比&#xff0c;在视频或图片展示类页面是一个重要功能。 本文介绍其常规的实现方法。 实现效果 当浏览器视口发生变化时&#xff0c;元素的尺寸随之变化&#xff0c;且宽高比不变。 代码实现 我们用最简单的元素结构来演示&#xff0c;实现宽高比为4&#xf…

鸿蒙Harmony是如何影响Android工程师的呢?

其实鸿蒙在2019就已经出来了&#xff0c;那时候还是套壳Android的。从2023年9月的发布会上&#xff0c;华为宣布鸿蒙原生应用全面启动、HarmonyOS NEXT亮相以后&#xff0c;围绕着纯血鸿蒙展开的鸿蒙应用生态发展迅猛&#xff0c;目前已经有包括社交、金融、影音、游戏、资讯、…

docker-compose和docker compose的区别

在docker实际使用中&#xff0c;经常会搭配Compose&#xff0c;用来定义和运行多个 Docker 容器。使用时会发现&#xff0c;有时候的指令是docker-compose&#xff0c;有时候是docker compose&#xff0c;下面给出解释。 docker官方文档&#xff1a;https://docs.docker.com/c…