首页 > 数据库 >MySQL之多表查询和子查询

MySQL之多表查询和子查询

时间:2024-09-10 19:25:36浏览次数:14  
标签:查询 dept emp 和子 之多表 where id select

一、多表查询

1、概述

MySQL 中的多表查询允许用户在单个查询语句中联合两个或多个表,依据表之间的关联关系来提取所需数据,这种技术在处理复杂数据关系时尤为常见和重要。

简单讲就是多表查询就是从两个或多个表中检索数据,当需要结合不同表中的信息时,通常会使用 JOIN 子句来实现表的连接,从而完成数据的整合。

2、表与表的关系

在数据库设计中,表与表之间的关系可以分为三种基本类型:

一对一关系(One-to-One):表示两个表中的记录是唯一匹配的。例如,“用户”表和“身份证信息”表之间的一对一关系意味着每个用户都对应着一条唯一的身份证信息记录。

一对多关系(One-to-Many):指的是一个表中的每条记录可以与另一个表中的多条记录相联系。比如,“班级”表和“学生”表之间的关系,一个班级可以有多个学生,但每个学生只属于一个班级。

多对多关系(Many-to-Many):在这种情况下,两个表中的记录都可以与对方的多条记录关联。例如,“学生”表和“课程”表之间的关系,一个学生可以选修多门课程,同时一门课程也可以被多个学生选修。为了有效地处理多对多关系,通常需要创建一个关联表或者叫做桥梁表来存储这两个表之间的关系。

3、多表查询

3.1、准备数据

-- 创建dept表

create table dept(
id int auto_increment comment 'ID' primary key,
name varchar(50) not null comment '部门名称'
)comment '部门表';

INSERT INTO dept (id, name) VALUES (1, '研发部'), (2, '市场部'),(3, '财务部'), (4,'销售部'), (5, '总经办'), (6, '人事部');

-- 创建emp表,并插入数据
create table emp(
id int auto_increment comment 'ID' primary key,
name varchar(50) not null comment '姓名',
age int comment '年龄',
job varchar(20) comment '职位',
salary int comment '薪资',
entrydate date comment '入职时间',
managerid int comment '直属领导ID',
dept_id int comment '部门ID'
)comment '员工表';

-- 添加外键
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);

INSERT INTO emp (id, name, age, job,salary, entrydate, managerid, dept_id)
VALUES
(1, '金庸', 66, '总裁',20000, '2000-01-01', null,5),
(2, '张无忌', 20, '项目经理',12500, '2005-12-05', 1,1),
(3, '杨逍', 33, '开发', 8400,'2000-11-03', 2,1),
(4, '韦一笑', 48, '开发',11000, '2002-02-05', 2,1),
(5, '常遇春', 43, '开发',10500, '2004-09-07', 3,1),
(6, '小昭', 19, '程序员鼓励师',6600, '2004-10-12', 2,1),
(7, '灭绝', 60, '财务总监',8500, '2002-09-12', 1,3),
(8, '周芷若', 19, '会计',48000, '2006-06-02', 7,3),
(9, '丁敏君', 23, '出纳',5250, '2009-05-13', 7,3),
(10, '赵敏', 20, '市场部总监',12500, '2004-10-12', 1,2),
(11, '鹿杖客', 56, '职员',3750, '2006-10-03', 10,2),
(12, '鹤笔翁', 19, '职员',3750, '2007-05-09', 10,2),
(13, '方东白', 19, '职员',5500, '2009-02-12', 10,2),
(14, '张三丰', 88, '销售总监',14000, '2004-10-12', 1,4),
(15, '俞莲舟', 38, '销售',4600, '2004-10-12', 14,4),
(16, '宋远桥', 40, '销售',4600, '2004-10-12', 14,4),
(17, '陈友谅', 42, null,2000, '2011-10-12', 1,null);

3.2、笛卡尔积

select * from emp,dept;

查询结果中出现的大量结果集(共102条记录)实际上是员工表 emp (共有17条记录)与部门表 dept (共有6条记录)之间的一种现象,称为笛卡尔积。

笛卡尔积发生在一个表中的每一行与另一个表中的每一行都进行了配对,生成的结果集是两个表行数的乘积,即 17 * 6 = 102。这种结果通常表明查询中没有正确地定义表之间的连接条件或者说 JOIN 条件缺失,导致了不想要的全部组合输出。为了避免这种情况,应该在查询中明确指定表之间的关联条件。

3.3、多表查询的分类

3.3.1内连接

在内连接查询中,只有那些满足连接条件的记录才会出现在结果集中。换句话说,内连接会找出两个表中相对应字段值相等的记录,并将这些记录组合成新的结果集返回。

select 字段... from 表1 inner join 表2 on 条件

inner可以省略

select * from emp join dept on emp.sept_id = dept.id;

只有 on 后面的条件成立的数据才会被查出来

3.3.2外连接

外连接(Outer Join)是一种数据库连接操作,它返回不仅是两个表中匹配的行,还包括某个表或两个表中的非匹配行。外连接可以分为左外连接(Left Outer Join)、右外连接(Right Outer Join)。

左外连接(Left Outer Join):返回所有左表(即出现在连接关键字左边的表)的记录,以及右表中与之匹配的记录。如果右表中没有匹配项,则结果集中的右表部分显示为NULL。
右外连接(Right Outer Join):与左外连接相反,返回所有右表的记录以及左表中与之匹配的记录。如果左表中没有匹配项,则左表部分显示为NULL。

左外连接:select 字段... from 表1 left outer join 表2 on 条件;

右外连接:select 字段... from 表1 right outer join 表2 on 条件

outer可省略。

 这就是左外连接,左表的数据全部显示,右表能关联上的显示,关联不上的显示为null。上面内连接时只有16行是因为陈友谅的dept_id是空,关联不上。

3.3.3字段显示 

如果是想要两个表中的某些字段,该字段必须非常的明确:

select id,name,dept_id from emp e left join dept d on e.dept_id = d.id ;

如果不明确他就不知道你需要的到底是哪个表里的该字段,就会报错

 如果是想要两个表中的某些字段,该字段必须非常的明确:

select emp.id,dept.name,dept_id from emp left join dept on emp.dept_id = dept.id ;

多表关联的时候,如果一个字段非常的明确,可以不在前面加表名,如果有多个表都有该字段,必须在字段前面指明是哪个表的字段,否则报错!!! 

3.3.4使用别名

如果表名特别⻓,每次写关联关系就特别的费劲,可以使⽤别名代替

select * from emp e left join dept d on e.dept_id = d.id ;

 mysql中 group by、  order by、   having 后面可以使用别名,where后面不能使用别名

二、子查询

子查询(Subquery)是在另一个查询语句内部执行的SELECT语句。子查询可以嵌套在主查询的WHERE子句、FROM子句或其他适当的位置中,用于过滤或生成主查询所需的中间结果。子查询通常用于处理更复杂的查询逻辑,如比较多个表中的数据、聚合计算或是生成临时表等。

1、分类

标量子查询:返回单一值的标量,最简单的形式。
列子查询:返回的结果集是 N 行一列。
行子查询:返回的结果集是一行 N 列。
表子查询:返回的结果集是 N 行 N 列。


2、实例

2.1标量子查询

标量子查询是指子查询的结果是一个单独的值,如一个数字、字符串或日期。这种类型的子查询通常在比较操作中使用,作为主查询的一个条件。
常用的操作符:= <> > >= < <=

需求:查询 "销售部" 的所有员工信息

首先要查出销售部的id  :select id from dept where name = '销售部';

再根据销售部的id去查询所有员工的id:select * from emp where dept_id = 4;

 但有时他们会让你只能使用一条sql去查,此时,子查询的作用就凸显出来了

select * from emp where dept_id = (select id from dept where name = '销售部');

轻松惬意解决问题 

2.2列子查询

列子查询是指子查询的结果是一列或多行一列的数据。这种类型的子查询通常用于在主查询中进行集合比较或者条件筛选。

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

操作符描述
IN在指定的集合范围内,多选一
NOT IN不在指定的集合范围之内
ANY子查询返回列表中,有一个满足即可
SOME与any等同,使用some的地方搜可以使用any
ALL子查询返回列表的所有值都必须满足

需求:查询 "销售部" 和 "市场部" 的所有员工信息

先查询"销售部" 和 "市场部"的id:

   select id from dept where name = '销售部' or name = '市场部';

在根据id查询员工信息:
       select * from emp where dept_id = 2 or dept_id = 4;

但使用子查询可以一下成功

select * from emp where dept_id in (select id from dept where name = '销售部' or name = '市场部');

 2.3行子查询

行子查询是指子查询的结果是一行或多列一行的数据。这种类型的子查询通常用于在主查询中查找与子查询结果完全匹配的记录。

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

需求:查询与 "张无忌" 的薪资及直属领导相同的员工信息

先查询"张无忌" 的薪资及直属领导:

    select salary,managerid from emp where name = '张无忌';

在查询和他一样的员工

select * from emp
where (salary,managerid) = (select salary, managerid from emp where name = '张无忌');

2.4表子查询

表子查询是指子查询的结果是多行多列的数据,相当于一个小型的表格。这种类型的子查询通常用于在主查询中作为数据源或者进行集合操作。

需求:查询与 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息

先查询与 "鹿杖客" , "宋远桥" 的职位和薪资

select job,salary from emp where name = '鹿杖客' or name = '宋远桥'

再查询与 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息

select * from emp where (job,salary) in (
select job,salary from emp where name = '鹿杖客' or name = '宋远桥') ;

若是更进一步,则是去掉"鹿杖客" , "宋远桥"这两个人,各位不妨思考一下怎么搞。

3、出现位置

子查询的各个分类说白了也就是子查询的出现位置

- 在where⼦句中: ⼦查询的结果可⽤作条件筛选时使⽤的值。
- 在from⼦句中: ⼦查询的结果可充当⼀张表或视图,需要使⽤表别名。
- 在having⼦句中: ⼦查询的结果可⽤作分组查询再次条件过滤时使⽤的值
- 在select⼦句中: ⼦查询的结果可充当⼀个字段。仅限⼦查询返回单⾏单列的情况。

上面的是出现在where中,下面讲讲出现在其他三个地方

3.1出现在from子句中

需求:查询员⼯的姓名,⼯资,及其部⻔的平均⼯资

部门平均工资: select dept_id,avg(salary) from emp group by dept_id;

 

 此时只要把上面查出来的结果当成一张表和emp表关联即可得到最后的答案

select name,salary,avgMoney from
emp ,(select dept_id,avg(salary) avgMoney from emp group by dept_id) avgTable
where emp.dept_id=avgTable.dept_id;

 3.2出现在having子句中

需求:查询平均⼯资⼤于1号部⻔的平均⼯资的部⻔号,和平均⼯资

1号部门的平均工资

select avg(salary) avg1 from emp where dept_id=1;

 

部门平均工资: select dept_id,avg(salary) from emp group by dept_id;

最后整合:

select dept_id,avg(salary) avgAll from emp
group by dept_id having avgAll > (select avg(salary) avg1 from emp where dept_id=1);

 3.3出现在select后面

需求:查询员⼯的姓名,⼯资,及其部⻔的平均⼯资

使用自连接,自己和自己连接

select name,salary, (select avg(salary) from emp e2 where e2.dept_id = e1.dept_id )
部门平均工资 from emp e1;

标签:查询,dept,emp,和子,之多表,where,id,select
From: https://blog.csdn.net/xieyichun_/article/details/142102873

相关文章

  • MySQL进阶(三)--多表查询
    3,多表查询多表查询顾名思义就是从多张表中一次性的查询出我们想要的数据。我们通过具体的sql给他们演示,先准备环境DROPTABLEIFEXISTSemp;DROPTABLEIFEXISTSdept;#创建部门表 CREATETABLEdept(didINTPRIMARYKEYAUTO_INCREMENT,dname......
  • sql查询字段截取
    SELECTCASEWHENSUBSTR(code,-2)='00'THENSUBSTR(code,1,LENGTH(code)-2)ELSEcodeENDAScodeFROMtest_table;说明:如果code最后两位是00的话,就截取掉,如果不是的话,就直接取code。......
  • MySQL(六)查询连续出现N次问题总结
    连续问题的本质单调递增的等差数列例如游戏连续签到7天可以获得奖品,连续出现3次的数字求解方法(1)确定什么属性连续出现三次,即哪一属性连续,哪一属性相等(2)增加额外的等差递增列,然后进行作差分组案例查询至少连续出现3次的数字Logs表:idnum11213142......
  • 保险公司如何用到IP地址查询?
    随着高新技术的日新月异,各大保险公司的服务方式也在逐渐完善,他们也在用更先进的数据分析技术来优化业务流程,提升客户体验和增强风险管理能力。其中,IP地址查询也是他们赖以依靠的技术之一。那么保险公司是如何在他们的领域去使用IP地址查询的呢?身份验证与反欺诈在保险行业中,......
  • Ignite系列1-jdbc连接,建表,查询示例
    一、JDBC方式连接Ignite集群    通过JDBC方式连接Ignite集群,执行SQL进行见表,mergeinto插入数据,并执行结果查询示例如下:/***测试ignitejdbc连接,简单创建按一张表,插入一条数据,然后查询出来,并验证字段是否正确*@throwsClassNotFoundException*......
  • LLog:Spring轻量级请求日志监控组件,集成管理面板,支持多条件查询检索
    开源地址https://gitee.com/lboot/LLog简介LLog是基于AOP构建的请求日志记录和查询工具库,通过引入该工具库,完成配置,实现对接口请求日志的记录、查询检索等功能。请求状态、时间、来源、耗时,请求参数,响应结果,作用接口记录支持与鉴权服务结合,记录请求来源为用户ID通过注解......
  • 2080. 区间内查询数字的频率
    题目链接2080.区间内查询数字的频率思路二分法(upper_bound-lower_bound)题解链接简洁写法:统计位置+二分查找(Python/Java/C++/Go/JS/Rust)关键点预先处理得到每个值所处位置的列表时间复杂度\(O(n+m\logn)\)空间复杂度\(O(n)\)代码实现:classR......
  • 查询出每个部门中,工资从高到低进行排名,工资部门排名在前 50%的员工
    1.查询出每个部门中,工资从高到低进行排名,工资部门排名在前50%的员工(比如部门有6个人,则前50%,则是前3名,如果部门人数为奇数,向下取整确定前50%的人数),如果其入职天数早于部门平均入职天数,还要列出其入职天数。如果其入职时间晚于部门平均入职天数,则入职天数显示为空要求查询的结......
  • 21.子查询
    SQL语句中嵌套SELECT语句,称谓嵌套查询,又称子查询。SELECT*FROMt1WHEREcolumn1=(SELECTcolumn1FROMt2);子查询外部的语句可以是INSERT/UPDATE/DELETE/SELECT的任何一个根据子查询结果可以分为:标量子查询(子查询结果为单个值)列子查询(子查询结果为一列)行子......
  • Mybatis骚操作-通用查询工具类
    老项目大多都有对JDBC进行了封装,可以直接执行SQL的工具类,在做项目升级改造的时候(这里仅指整合mybatis),要么全部调整成dao-xml的形式(会有改动代码多的问题,而且看代码时需要xml和java来回切换),要么维持原逻辑不改动(跟mybatis基本无关,同样难以用到mybatis的配置)这里实现个可以让工具使......