当前位置: 首页 > news >正文

mysql多表查询

1.多表关系

  • 一对多(多对一)
  • 多对多
  • 一对一       

2.案例 

2.1一对多

案例:部门与员工

关系:一个部门对应多个员工,一个员工对应一个部门。

实现:在多的一方建立外键,只想一方的主键。

2.2多对多

案例:学生与课程

关系:一个学生可选择多门课程,一门课程可供多个学生选择。

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

2.3一对一

案例:用户与用户详情

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

实现:在任意一方加入外键,关联另一方的主键,并设置外键为唯一的(unique)

 

3.准备工作

3.1部门表的创建和数据插入

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

# 插入数据
insert into dept(name) values ('研发部'),('市场部'),('财务部'),('销售部'),('总经办');

3.2 创建员工表和数据插入

# 员工表
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 '员工表';

insert into emp 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-07-09',3,1),
                    (6,'小昭',19,'程序员鼓励师',6600,'2004-10-12',2,1),
                    (7,'灭绝',60,'财务总监',8500,'2002-09-12',1,3),
                    (8,'周芷若',19,'会计',4800,'2006-06-02',7,3),
                    (9,'丁敏君',23,'出纳',5250,'2009-05-12',7,3),
                    (10,'赵敏',20,'市场部总监',12500,'2002-02-05',1,2),
                    (11,'鹿杖客',56,'职员',3750,'2006-12-05',10,2),
                    (12,'鹤笔翁',19,'职员',3750,'2006-05-25',10,2),
                    (13,'方东白',19,'职员',5500,'2002-11-05',10,2),
                    (14,'张三丰',88,'销售总监',14000,'2003-06-15',1,4),
                    (15,'俞莲舟',38,'销售',4600,'2003-07-05',14,4),
                    (16,'宋远桥',40,'销售',4600,'2004-09-18',14,4),
                    (17,'陈友谅',42,null,2000,'2010-06-16',1,null);

 4.sql语句查询

4.1内连接查询

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

4.1.1隐式内连接

语法 select 字段列表 from table1,table2 where 条件...;

查询员工信息及其对应部门信息。

select d.name as dname,e.name from dept d,emp e where d.id=e.dept_id;

4.1.2显示内连接

语法:select 字段列表 from table1 [inner] join  table2 on 链接条件...;(中括号内字段可省略不写)。

查询员工信息及其对应部门信息。

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

查询结果:

[
  {
    "dname": "总经办",
    "name": "金庸"
  },
  {
    "dname": "研发部",
    "name": "张无忌"
  },
  {
    "dname": "研发部",
    "name": "杨逍"
  },
  {
    "dname": "研发部",
    "name": "韦一笑"
  },
  {
    "dname": "研发部",
    "name": "常遇春"
  },
  {
    "dname": "研发部",
    "name": "小昭"
  },
  {
    "dname": "财务部",
    "name": "灭绝"
  },
  {
    "dname": "财务部",
    "name": "周芷若"
  },
  {
    "dname": "财务部",
    "name": "丁敏君"
  },
  {
    "dname": "市场部",
    "name": "赵敏"
  }
]

4.2外连接 

4.2.1左外连接

查询左表的所有数据,以及两张表的交集部分。

语法:select 字段列表 from table1 left [outer] join table2 on 条件。

查询所有员工的信息和部门名称;

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

查询结果,左外连接:查询左表的所有数据,以及两张表的交集部分。所以最后一条即使没有对应的部门也会查出来。

4.2.2右外连接

查询右表的所有数据,以及两张表的交集部分。

语法:select 字段列表 from table1 right [outer] join table2 on 条件。

查询员工的信息和部门名称;

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

查询结果,右外连接查询的是dept全部信息和emp的交集,不会出现4.2.1那种查询结果。

4.2.3总结

左外连可以查到到没有dept的emp的信息,右外链可以查到没有emp的dept。

4.3自链接查询

当前表与自身的链接查询,子链接不许使用别名。

语法:select 字段列表 from table a join table b on 条件。。。;

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

查询员工及其领导的名字(内连接)

select e.name,p.name managername from emp e inner join emp p on e.managerid=p.id;

结果,查询出emp 自身的交集

查询员工及其领导的名字(左连接)

select e.name,p.name managername from emp e left join emp p on e.managerid=p.id;
查询员工及其所属领导的名字,即使没有领导也要查出来:

4.4联合查询

把多次查询的结果合并,形成一个新的查询集。

语法

select 字段列表 from table1 ...

union [all] 

select 字段列表 from table2 ...;

注意事项:

  • union all 会有重复结果,union不会
  • 联合查询比使用or效率高,不会是索引失效
  • 联合查询的多张表的列数必须保持一直,字段类型也需要保持一致。
    

 查询信息大于5000,年龄大于50岁。

select * from emp where salary >5000
                  union
                  select * from emp where age>50;

查询结果:

5.子查询

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

5.1标量子查询

子查询结果为单个值(数字,时间,字符串等)。

常用操作:<> ,>,>=,=<,=

查询销售部所有的员工


# 第一步 id=4
select dept.id from dept where name='销售部';
# 第二部,根据第一步查询的结果
select * from emp where emp.dept_id=4;
# 标量子查询(合并)
select * from emp where  dept_id=(select id from dept where name='销售部');

5.2列子查询

返回的结果是一列(可以是多行)

操作符描述
IN在指定的范围合集内,多选一
NOT IN不在指定的范围合计内
ANY子查询返回的列表中,右任意一个满足即可
SOME与ANY等同
ALL子查询返回的所有值都必须满足

查询销售部和市场部所有员工信息

#第一步:通过dept表获取市场部和销售部id
select id from dept where name='市场部' or name='销售部';
# 第二部:通过上一步获取id,查询员工信息
select * from emp where dept_id in (2,4);
# 合并
select * from emp where dept_id in (select id from dept where name='市场部' or name='销售部');

结果

查询比财务部所有人都高的员工工资

# 第一步获取财务部id
select  id from dept where name='财务部';
# 第二部获取财务部最高工资
select  max(salary) from emp where dept_id='3';
#第三步获取高于财务部最高工资的员工信息
select * from  emp where salary>8500;
# 合并
select * from  emp where salary>all(select  salary from emp where dept_id=(select  id from dept where name='财务部'));

 结果

#查询比财务部一些人工资高的员工。

select * from  emp where salary>some(select  salary from emp where dept_id=(select  id from dept where name='财务部'));
select * from  emp where salary>any(select  salary from emp where dept_id=(select  id from dept where name='财务部'));

结果

5.3行子查询

返回的子查询结果是一行(可以是多列)。

常用操作符:=,<,>,,in,not in


# 第一步获取张无忌的薪资和领导id
select  salary,managerid from emp where name='张无忌';
# 第二部根据第一部信息查询员工信息
select * from emp where salary=12500 and managerid=1;
# 合并
select * from emp where (salary,managerid)=(select  salary,managerid from emp where name='张无忌');

结果:

5.4表子查询

子查询结果多行多列:

常用操作符:in

查询与赵敏或周芷若相同薪资和领导的员工。

select * from emp where (salary,managerid) in (select salary,managerid from emp where name='赵敏' or name='周芷若');

结果:

6.多对多查询

准备工作

学生表

create table student(

                        id int auto_increment  key comment '主键ID',

                        name varchar(10) comment '姓名',

                        no varchar(10) comment '学号'

)comment ' 学生表';
insert into student values (null,'黛绮丝','2000100101'),(null,'谢逊','2000100102'),(null,'殷天正','2000100103'),(null,'韦一笑','2000100104');

课程表:

create table course(
                       id int auto_increment  key comment '主键ID',
                       name varchar(10) comment '课程名称'
)comment '课程表';



insert into course values (null,'Java'),(null,'PHP'),(null,'Mysql'),(null,'Hadoop')

课程学生关联表:

create table student_course(

                               id int auto_increment comment '主键'  key,

                               studentid int not null comment '学生ID',

                               courseid int not null comment '课程ID',

                               constraint fk_courseid foreign key (courseid) references course(id),

                               constraint fk_studentid foreign key (studentid) references student(id)

)comment '学生课程中间表';



insert into student_course values (null,1,1),(null,1,2),(null,1,3),(null,2,3),(null,3,4);

 查询学生选修的课程

select student.name,course.name from course,student,student_course where student.id=student_course.studentid and course.id=student_course.courseid;

结果:

相关文章:

  • 【嵌入式Linux应用开发基础】网络编程(4):UDP协议
  • 数字可调控开关电源设计(论文+源码)
  • Windows 图形显示驱动开发-WDDM 3.2-自动显示切换(七)
  • ubuntu安装docker compose
  • 2015-2025大连社保年度缴费基数
  • 说一下类装载的执行过程?
  • JxBrowser 7.42.1 版本发布啦!
  • 对话式AI引擎:DeepSeek技术引领多模态交互新篇章
  • 刚充值Deepseek账号,但接入官方的API却遇到了问题【VSCode Cline Cursor Deepseek deepseek-reasoner】
  • 表单验证和正则表达式
  • debain12.9安装unsloth大模型微调环境
  • 为什么用match case 而不用if else
  • 算法-二叉树篇11-左叶子之和
  • 计算机网路:自顶向下方法——第三章 运输层
  • 如何评估 LLM:大型语言模型评估方法全解析与综述
  • 【Linux 操作系统】进程管理 - 冯诺依曼体系|进程|环境变量|进程地址空间
  • 服务器间迁移conda环境
  • 【字符串】最长公共前缀 最长回文子串
  • 保护密码等敏感信息的几个常用方法
  • HTML邮件的制作以及遇到的问题
  • 马上评|让“贾宝玉是长子长孙”争议回归理性讨论
  • 东莞“超级”音乐节五一出圈背后:文旅热力何以澎湃经济脉动
  • 现场丨“影像上海”启幕:串联摄影、电影与当代艺术
  • 44岁街舞运动推广者、浙江省街舞运动协会常务理事钟永玮离世
  • 深圳下调公积金利率,209万纯公积金贷款总利息减少9.94万
  • 美联储连续第三次维持利率不变,警示关税影响