【MySQL】复合查询

目录

  • 一、基本查询回顾
    • [1.1 查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J](#1.1 查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J)
    • [1.2 按照部门号升序而雇员的工资降序排序](#1.2 按照部门号升序而雇员的工资降序排序)
    • [1.3 使用年薪进行降序排序](#1.3 使用年薪进行降序排序)
    • [1.4 显示工资最高的员工的名字和工作岗位](#1.4 显示工资最高的员工的名字和工作岗位)
    • [1.5 显示工资高于平均工资的员工信息](#1.5 显示工资高于平均工资的员工信息)
    • [1.6 显示每个部门的平均工资和最高工资](#1.6 显示每个部门的平均工资和最高工资)
    • [1.7 显示平均工资低于2000的部门号和它的平均工资](#1.7 显示平均工资低于2000的部门号和它的平均工资)
    • [1.8 显示每种岗位的雇员总数,平均工资](#1.8 显示每种岗位的雇员总数,平均工资)
  • 二、多表查询
    • [2.1 显示雇员名、雇员工资以及所在部门的名字](#2.1 显示雇员名、雇员工资以及所在部门的名字)
    • [2.2 显示部门号为10的部门名,员工名和工资](#2.2 显示部门号为10的部门名,员工名和工资)
    • [2.3 显示各个员工的姓名,工资,及工资级别](#2.3 显示各个员工的姓名,工资,及工资级别)
  • 三、自连接
    • [2.1 显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号--empno)](#2.1 显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号--empno))
  • 四、子查询
    • [4.1 在where子句中使用的子查询](#4.1 在where子句中使用的子查询)
      • [4.1.1 单行子查询](#4.1.1 单行子查询)
        • [4.1.1.1 显示SMITH同一部门的员工](#4.1.1.1 显示SMITH同一部门的员工)
      • [4.1.2 多行子查询](#4.1.2 多行子查询)
        • [4.1.2.1 查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的](#4.1.2.1 查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的)
        • [4.1.2.2 显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号](#4.1.2.2 显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号)
        • [4.1.2.3 显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)](#4.1.2.3 显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工))
      • [4.1.3 多列子查询](#4.1.3 多列子查询)
        • [4.1.3.1 查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人](#4.1.3.1 查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人)
    • [4.2 在from子句中使用的子查询](#4.2 在from子句中使用的子查询)
      • [4.2.1 显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资](#4.2.1 显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资)
      • [4.2.2 查找每个部门工资最高的人的姓名、工资、部门、最高工资](#4.2.2 查找每个部门工资最高的人的姓名、工资、部门、最高工资)
      • [4.2.3 显示每个部门的信息(部门名,编号,地址)和人员数量](#4.2.3 显示每个部门的信息(部门名,编号,地址)和人员数量)
    • [4.3 合并查询](#4.3 合并查询)
      • [4.3.1 将工资大于2500或职位是MANAGER的人找出来](#4.3.1 将工资大于2500或职位是MANAGER的人找出来)
  • 结尾

一、基本查询回顾

准备工作,创建一个雇员信息表(来自oracle 9i的经典测试表)

  • EMP员工表
  • DEPT部门表
  • SALGRADE工资等级表
cpp 复制代码
DROP database IF EXISTS `scott`;
CREATE database IF NOT EXISTS `scott` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

USE `scott`;

DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
  `deptno` int(2) unsigned zerofill NOT NULL COMMENT '部门编号',
  `dname` varchar(14) DEFAULT NULL COMMENT '部门名称',
  `loc` varchar(13) DEFAULT NULL COMMENT '部门所在地点'
);

DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
  `empno` int(6) unsigned zerofill NOT NULL COMMENT '雇员编号',
  `ename` varchar(10) DEFAULT NULL COMMENT '雇员姓名',
  `job` varchar(9) DEFAULT NULL COMMENT '雇员职位',
  `mgr` int(4) unsigned zerofill DEFAULT NULL COMMENT '雇员领导编号',
  `hiredate` datetime DEFAULT NULL COMMENT '雇佣时间',
  `sal` decimal(7,2) DEFAULT NULL COMMENT '工资月薪',
  `comm` decimal(7,2) DEFAULT NULL COMMENT '奖金',
  `deptno` int(2) unsigned zerofill DEFAULT NULL COMMENT '部门编号'
);

DROP TABLE IF EXISTS `salgrade`;
CREATE TABLE `salgrade` (
  `grade` int(11) DEFAULT NULL COMMENT '等级',
  `losal` int(11) DEFAULT NULL COMMENT '此等级最低工资',
  `hisal` int(11) DEFAULT NULL COMMENT '此等级最高工资'
);

insert into dept (deptno, dname, loc)
values (10, 'ACCOUNTING', 'NEW YORK');
insert into dept (deptno, dname, loc)
values (20, 'RESEARCH', 'DALLAS');
insert into dept (deptno, dname, loc)
values (30, 'SALES', 'CHICAGO');
insert into dept (deptno, dname, loc)
values (40, 'OPERATIONS', 'BOSTON');

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, null, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, null, 10);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7839, 'KING', 'PRESIDENT', null, '1981-11-17', 5000, null, 10);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7844, 'TURNER', 'SALESMAN', 7698,'1981-09-08', 1500, 0, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, null, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, null, 10);

insert into salgrade (grade, losal, hisal) values (1, 700, 1200);
insert into salgrade (grade, losal, hisal) values (2, 1201, 1400);
insert into salgrade (grade, losal, hisal) values (3, 1401, 2000);
insert into salgrade (grade, losal, hisal) values (4, 2001, 3000);
insert into salgrade (grade, losal, hisal) values (5, 3001, 9999);

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

cpp 复制代码
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';

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

cpp 复制代码
select * from emp order by deptno asc , sal desc;

1.3 使用年薪进行降序排序

cpp 复制代码
select *,sal*12+ifnull(comm,0) 年薪 from emp order by 年薪 desc;

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

cpp 复制代码
select ename,job from emp where sal = (select max(sal) from emp);

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

cpp 复制代码
select * from emp where sal > (select avg(sal) from emp);

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

cpp 复制代码
select deptno,avg(sal) 平均 , max(sal) 最高 from emp group by deptno;

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

cpp 复制代码
select deptno,avg(sal) 平均 from emp group by deptno having 平均<2000;

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

cpp 复制代码
select job,avg(sal) 平均 from emp group by job;

二、多表查询

实际开发中往往数据来自不同的表,所以需要多表查询。这里我用EMP,DEPT,SALGRADE这三张表来演示如何进行多表查询。

从第一张表中取第一条数据,与第二张表中所有的数据进行组合,从第一张表中取第二条数据,与第二张表中所有的数据进行组合,重复上面的步骤,然后不加过滤条件,得到的结果就是笛卡尔积

2.1 显示雇员名、雇员工资以及所在部门的名字

因为雇员名、雇员工资,部门的名字这些数据分别来自EMP和DEPT表,因此要联合查询。

下面我将EMP和DEPT表进行笛卡尔积,发现形成了一个更大的表,表中有很多同一个人的数据,并且一行数据中还有部门号不同的数据,显然这就是无用的数据,需要将这些数据筛除掉。

cpp 复制代码
select ename,job,emp.deptno from emp,dept where emp.deptno=dept.deptno;

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

cpp 复制代码
select dname,ename,sal from emp,dept where emp.deptno=dept.deptno and emp.deptno=10;

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

因为员工的姓名、工资相关数据来自EMP表,工资级别相关数据来自于SALGRADE表,所以这里需要对两张表进行笛卡尔积。

cpp 复制代码
select ename,sal,grade,losal,hisal from emp,salgrade where sal between losal and hisal;

三、自连接

自连接是指在同一张表连接查询,进行自连接时,由于使用的是同一个表名,直接使用会报错,所以需要给表取别名。


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

  • 自连接
cpp 复制代码
select t2.empno,t2.ename from emp t1,emp t2 where t1.mgr=t2.empno and t1.ename='FORD';
  • 子查询
cpp 复制代码
select empno,ename from emp where empno = (select mgr from emp where ename='FORD');

四、子查询

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

  • in关键字 :用于判断某个值是否存在于一个指定的集合中,这个集合可以是一个具体的值列表,也可以是一个子查询的结果集。
  • all关键字 :会将一个值与子查询返回的所有值进行比较,只有当该值满足与子查询返回的所有值的比较条件时,才会返回 TRUE。
  • any关键字 :会将一个值与子查询返回的任意一个值进行比较,只要该值满足与子查询返回的任意一个值的比较条件,就会返回 TRUE。

4.1 在where子句中使用的子查询

4.1.1 单行子查询

单行子查询就是返回一行数据的子查询。

4.1.1.1 显示SMITH同一部门的员工
cpp 复制代码
select * from emp where deptno = (select deptno from emp where ename='SMITH');

4.1.2 多行子查询

多行子查询查询就是返回多行数据的子查询。

4.1.2.1 查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的
cpp 复制代码
select ename,job,sal,deptno from emp where job in(select distinct job from emp where deptno=10) and deptno<>10;

4.1.2.2 显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
cpp 复制代码
select ename,sal,deptno from emp where sal > (select max(sal) from emp where deptno=30);

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

4.1.2.3 显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)
cpp 复制代码
select ename,sal,deptno from emp where sal > (select min(sal) from emp where deptno=30);

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

4.1.3 多列子查询

多列子查询就是指查询返回多个列数据的子查询语句

4.1.3.1 查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人
cpp 复制代码
select * from emp where (deptno,job)=(select deptno,job from emp where ename='SMITH') and ename<>'SMITH';

select * from emp where (deptno,job)in(select deptno,job from emp where ename='SMITH') and ename<>'SMITH';

4.2 在from子句中使用的子查询

子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。不要单纯的认为只有内存/磁盘中存储真实存在的表结构才是表,我们筛选出来的也是表。

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

cpp 复制代码
select ename,t1.deptno,sal,myavg from emp t1,(select deptno,avg(sal) myavg from emp group by deptno) t2 where t1.deptno=t2.deptno and sal > myavg;

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

cpp 复制代码
select ename,sal,t1.deptno,mymax from emp t1,(select deptno,max(sal) mymax from emp group by deptno) t2 where t1.deptno=t2.deptno and sal = mymax;

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

cpp 复制代码
select dname,t1.deptno,loc,mycnt from dept t1,(select deptno,count(*) mycnt from emp group by deptno) t2 where t1.deptno=t2.deptno;

4.3 合并查询

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

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

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

cpp 复制代码
select * from emp where sal>2500 union select * from emp where job='MANAGER';

select * from emp where sal>2500 union all select * from emp where job='MANAGER';

结尾

如果有什么建议和疑问,或是有什么错误,大家可以在评论区中提出。

希望大家以后也能和我一起进步!!🌹🌹

如果这篇文章对你有用的话,希望大家给一个三连支持一下!!🌹🌹

相关推荐
CYRUS_STUDIO18 分钟前
Android 自定义变形 MD5 算法
android·算法·安全
nuc-1271 小时前
sqli-labs学习笔记3
数据库·笔记·学习·sqli-labs
大小科圣2 小时前
基于redis实现会话保持
数据库·redis·git
雨声不在2 小时前
手动集成sqlite的方法
android·sqlite
LCY1332 小时前
数据库与其所用数据结构
数据结构·数据库
居然是阿宋3 小时前
TextView、AppCompatTextView和MaterialTextView该用哪一个?Android UI 组件发展史与演进对照表
android·ui
dblens 数据库管理和开发工具3 小时前
精挑20题:MySQL 8.0高频面试题深度解析——掌握核心知识点、新特性和优化技巧
数据库·mysql·面试
Psycho_MrZhang3 小时前
Docker DockerFile和Django最佳实践
数据库·docker·django
fananchong23 小时前
MySQL InnoDB 事务隔离级别和锁
sql·mysql·innodb··事务隔离级别
李匠20244 小时前
C++学习之redis
数据库·redis·缓存