MySql学习4:多表查询

教程来源

黑马程序员 MySQL数据库入门到精通,从mysql安装到mysql高级、mysql优化全囊括

多表关系

各个表结构之间存在各种关联关系,基本上分为三种:一对多(多对一)、多对多、一对一

一对多(多对一)

例如:部门与员工的关系。一个部门对应多个员工、一个员工对应一个部门(不考虑一个员工对应多个部门的情况)

实现:在多的一方建立外键,指向一的一方的主键

多对多

例如:学生与课程的关系。一个学生可以选修多门课程,一门课程也可以供多个学生选择

实现:建立第三张中间表,中间表至少包含两个外键,分别关联两份主键


一对一

例如:用户与用户详情的关系。一对一关系多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率。

比如:提高查询性能,当一张表中数据过多时查询会变得缓慢;可以使数据库结构更清晰,每个表的结构更加简单

可以在任何一方加入外键,关联另一方的主键,并且设置外键为唯一的。

多表查询概述

指从多张表中查询数据。

笛卡尔积

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

分类

  • 连接查询

    • 内连接:相当于查询A、B交集的部分
    • 外连接:
      • 左外连接:查询左表所有数据,以及两张表交集部分数据
      • 右外连接:查询右表所有数据 ,以及两张表交集部分数据
    • 自连接:当前表与自身的连接查询,自连接必须使用表别名
  • 子查询

内连接

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

隐式内连接

dart 复制代码
select 字段 from 表1,表2 where 条件

显示内连接

dart 复制代码
select 字段列表 from 表1 join 表2 on 连接条件

查询员工工号、姓名及所在部门的名称

dart 复制代码
// 隐式内连接
select emp.workno,emp.name,dept.dept_name  from emp,dept where emp.dept_id = dept.id;
// 显示外连接
select emp.workno,emp.name,dept.dept_name from emp join dept on emp.dept_id = dept.id;

外连接

左外连接

dart 复制代码
select 字段 from 表1 left join 表2 on 条件

查询emp表的所有数据,和对应的部门信息

dart 复制代码
select emp.*,dept.dept_name  from emp left join dept on emp.dept_id = dept.id;

这里与内连接的区别,假如有一个新员工刚入职还没有对应的部门,内连接是不会查询出该员工的信息,而左外连接会查询到该信息。

内连接是两边都要有;左外连接是左边都要有,右边可以不要有

右外连接

dart 复制代码
select 字段 from 表1 right join 表2 on 条件

查询dept的所有数据,和对应的员工表的信息

自连接

dart 复制代码
select 字段列表 from 表A join 表A 别名B  on 条件

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

例如,当表中的数据具有层级结构时,可以使用自连接来查询父子关系或者层级关系。比如,在员工表中查询员工的上级领导或者下属。

自连接可以帮助我们在同一表中进行比较和分析操作,解决一些复杂的查询需求。但是需要注意,在使用自连接时需要谨慎处理好连接条件,避免出现无限循环或者性能问题。

dart 复制代码
select emp.*,a.name  from emp join emp as a where emp.manager_id = a.id ;

联合查询

联合查询就是把多次查询的结果合并起来,形成一个新的查询结果集。比如,查询出薪资低于5000的员工和年龄大于60的员工。

关键字:union all union,后者是对前者的一个数据去重。

联合查询时多张表的列数必须保持一致、字段类型也需要保持一致。

dart 复制代码
select 字段列表 from a 条件
union 
select 字段列表 from b 条件

子查询

SQL中嵌套select语句,称为嵌套查询,又称子查询。

dart 复制代码
select * from t1 where column1 = (select column1 from t2)

子查询的外部语句可以是insertdeleteupdateselect中的任何一个

根据子查询的结果,可以分为:

  • 标量子查询,子查询结果是单个值
  • 列子查询,子查询的结果是一列
  • 行子查询,子查询的结果是一行
  • 表子查询,子查询的结果为多行多列

标量子查询

子查询返回的结果是单个值(数字、字符串、日期等),这种子查询称为标量子查询。

常用的操作符有:><!==

查询出研发中心的所有员工信息:

1)先查询出研发中心的部门id

2)根据部门id查询员工信息

dart 复制代码
select * from emp where dept_id = (select id from dept where dept_name = '研发中心')

列子查询

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

常用的操作符有:innot inandsomeall

查询交付中心和研发中心的所有员工信息

1)查询出交付中心和研发中心的部门id

2)根据部门id查询员工信息

dart 复制代码
select * from emp where dept_id  in (select id from dept where dept_name in ('交付中心','研发中心'))

行子查询

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

常用的操作符有:><!==

查询与秦一的性别相同的同部门员工信息

1)查询秦一的性别与部门id

2)根据性别和部门id查询员工信息

dart 复制代码
select * from emp where (sex ,dept_id) = (select sex ,dept_id  from emp where name = '秦一')

表子查询

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

常用操作符:in

查询与秦一、李二的性别和部门相同的员工信息

dart 复制代码
select * from emp where (sex ,dept_id) in (select sex ,dept_id  from emp where name = '秦一' or name = '李二')

查询入职日期是2023-06-12之后的员工信息,及其部门信息

dart 复制代码
select e.*,d.* from (select * from emp where entrydata > '2023-06-12') as e 
left join dept as d on e.dept_id = d.id
相关推荐
张3蜂15 分钟前
Ubuntu系统安装mysql、nginx、.netcore
mysql·nginx·ubuntu
没明白白34 分钟前
Redis 缓存雪崩、缓存穿透、缓存击穿详解
数据库·redis·缓存
gbase_lmax34 分钟前
gbase8s数据库常见的索引扫描方式
数据库
雅冰石1 小时前
mysql怎样优化count(*) from 表名 where …… or ……这种慢sql
mysql
阳光九叶草LXGZXJ1 小时前
南大通用数仓-GCDW-学习-03-用户管理
linux·运维·数据库·学习
学博成2 小时前
MySQL5.7主从复制集群如何配置半同步复制
mysql
Islucas2 小时前
入门Django
数据库·django·sqlite
jnrjian2 小时前
update 强制 NEST_LOOP NL 的理解,被驱动表 inner table
数据库·sql·oracle
新知图书3 小时前
SQL Server 2022的数据类型
数据库·oracle
脑子不好真君3 小时前
MongoDB的备份和恢复命令
数据库·mongodb