基础篇04——多表查询

多表关系

一对多

多对多

多对多是通过中间表实现的

-- 创建学生表
create table student
(
    id   int auto_increment primary key comment 'ID',
    name varchar(10) comment '姓名',
    no   varchar(3) comment '学号'
) comment '学生表';

insert into student
values (null, '黛绮丝', '001'),
       (null, '谢逊', '002'),
       (null, '小明', '003'),
       (null, '小红', '004');

-- 创建课程表
create table course
(
    id   int auto_increment primary key comment 'ID',
    name varchar(10) comment '课程名称'
) comment '课程表';

insert into course
values (null, '语文'),
       (null, '数学'),
       (null, '英语');

-- 创建中间表,维护学生表和课程表之间的关系
create table student_course
(
    id        int auto_increment primary key comment 'ID',
    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, 2),
       (null, 2, 3),
       (null, 3, 3);

一对一 

-- 创建用户表
create table tb_user
(
    id     int auto_increment primary key comment 'ID',
    name   varchar(10) comment '姓名',
    age    tinyint unsigned comment '年龄',
    gender char(1) comment '性别',
    phone  char(11) comment '手机号'
) comment '用户基本信息表';

-- 创建用户教育信息表
create table tb_user_edu
(
    id            int auto_increment primary key comment 'ID',
    degree        varchar(20) comment '学历',
    major         varchar(50) comment '专业',
    primaryschool varchar(50) comment '小学',
    middleschool  varchar(50) comment '中学',
    university    varchar(50) comment '大学',
    userid        int unique comment '用户ID',
    constraint fk_userid foreign key (userid) references tb_user (id)
) comment '用户教育信息表';

insert into tb_user(id, name, age, gender, phone)
values (null, '小明', 16, '1', '10000000001'),
       (null, '小花', 13, '2', '10000000002'),
       (null, '小华', 15, '1', '10000000003'),
       (null, '小红', 14, '2', '10000000004');

insert into tb_user_edu(id, degree, major, primaryschool, middleschool, university, userid)
values (null, '本科', '舞蹈', 'XXX小学', 'XXX中学', 'XXX大学', 1),
       (null, '大专', '会计', 'YYY小学', 'YYY中学', 'YYY大学', 2),
       (null, '硕士', '英语', 'AAA小学', 'AAA中学', 'AAA大学', 3),
       (null, '博士', '临床医学', 'BBB小学', 'BBB中学', 'BBB大学', 4);

多表查询概述

多表查询指的是从多张表中查询数据

用以下例子举例

笛卡尔积

当直接查询两张表时(即执行命令:select * from emp,  dept;),查询的结果就是笛卡尔积,查询结果数为两张表的数据量相乘,我们需要消除无效的笛卡尔积,如下

select *
from emp,
     dept
where emp.dept_id = dept.id;

 多表查询分类

内连接

-- 隐式内连接实现:查询每一个员工姓名及其所属部门名称
select emp.name, dept.name
from emp,
     dept
where dept_id = dept.id;

-- 显式内连接实现:查询每一个员工姓名及其所属部门名称
-- 可以给表起别名来简化代码,但是起别名之后不能再用表原来的名称
-- inner关键字可以省略
select e.name, d.name
from emp e
         inner join dept d on e.dept_id = d.id;

外连接

左外连接和右外连接可以相互转换,即左外连接可以用右外连接替代,右外连接也可以用左外连接替代,只需要更改关键字left、right和两个表的位置即可,这里就不展示了。 

-- 查询emp表的所有数据,和对应的部门信息(左外连接)
-- outer 关键字可以省略
-- from 后跟着的表为左表,join后跟着的表为右表
-- 两个表的顺序不一样查询结果也不一样
-- 左外连接表示展示左表的所有数据,以及左表中每一条数据对应的右表数据,如果右表没有数据则显示为空
-- 右外连接则反过来,表示展示右表的所有数据,以及右表中每一条数据对应的左表数据,如果左表没有数据则显示为空
-- 自己运行一下代码就可以明白
select e.*, d.name  -- e.* 表示查询emp表中的所有数据
from emp e
         left outer join dept d
                         on e.dept_id = d.id;

-- 查询所有的部门信息,和对应的emp表数据(右外连接(
select d.*, e.*
from emp e
         right outer join dept d on d.id = e.dept_id;

自连接

自连接的外连接查询可以是左外也可以是右外。

-- 查询所有员工的名字及其所属领导的名字
-- 显式内连接实现
select e1.name as '员工姓名', e2.name as '领导姓名'
from emp e1
         join emp e2 on e1.managerid = e2.id;

-- 隐式内连接实现
select e1.name '员工姓名', e2.name '领导姓名'
from emp e1,
     emp e2
where e1.managerid = e2.id;

-- 查询所有员工的名字及其所属领导的名字,如果员工没有领导也要查询出来
-- 这里用外连接实现,用的是左外连接
select e1.name '员工姓名', e2.name '领导姓名'
from emp e1
         left join emp e2 on e1.managerid = e2.id;

联合查询union

-- 将薪资低于5000的员工和年龄大于40的员工全部查询出来
-- 即员工满足两个条件之一就需要被查询出来
-- 有 all 关键字查询结果不去重,没有 all 则会将查询结果去重
-- 只有 select 和 from 之间的字段列表的列数和类型一致时才可以用联合查询
select *
from emp
where salary < 5000
union all
select *
from emp
where age > 40;

子查询

子查询一般都用小括号括起来,可以放在 select、from、where 这几个位置(具体看后面案例)

标量子查询

-- 查询研发部的所有员工信息
select *
from emp
where dept_id = (select id from dept where dept.name = '研发部');

列子查询

-- 查询销售部和市场部的所有员工信息
select *
from emp
where dept_id in (select dept.id
                  from dept
                  where dept.name in ('销售部', '市场部'));



-- 查询比财务部 所有人 工资都高的员工信息
-- 查询财务部的id:select id from dept where dept.name = '财务部'
-- 先查出财务部员工最高的工资
-- select max(salary) from emp where dept_id = (select id from dept where dept.name = '研发部');
-- 实现方式1:
select *
from emp
where salary > (select max(salary)
                from emp
                where dept_id = (select id
                                 from dept
                                 where dept.name = '财务部'));

-- 实现方式2:(all)
select *
from emp
where salary > all (select salary
                    from emp
                    where dept_id = (select id
                                     from dept
                                     where dept.name = '财务部'));


-- 查询比研发部 任意一人 工资高的员工信息(any/some)
select *
from emp
where salary > any (select salary
                    from emp
                    where dept_id = (select id
                                     from dept
                                     where dept.name = '研发部'));

行子查询

-- 查询与“张无忌”薪资及直属领导相同的员工信息
-- 先查出张无忌的薪资和指数领导id
# select salary, managerid from emp where name='张无忌';
# 假设查出结果为(10000, 1)
# (salary, managerid) = ( select ...) => salary=10000 and managerid=1
select *
from emp
where (salary, managerid) = (select salary, managerid from emp where name = '张无忌');

表子查询

-- 查询与 小明,小红 的职位和薪资相同的员工信息
# 1、查询小明,小红 的职位和薪资
select job, salary
from emp
where name in ('小明' '小红');
select *
from emp
where (job, salary) in (select job, salary
                        from emp
                        where name in ('小明' '小红'));

-- 查询入职日期是'2018-01-01'之后的员工信息及其部门信息
# 查询入职日期是'2006-01-01'之后的员工id
select id
from emp
where entrydate > '2006-01-01';

# (select * from emp where entrydate > '2006-01-01') 查询结果作为一张临时表
# 给临时表起别名为 e
select e.*, d.name
from (select * from emp where entrydate > '2006-01-01') e
         left join dept d on e.dept_id = d.id;

多表查询案例练习

上面的例子涉及之前所说的emp员工表、dept部门表和薪资等级表,薪资等级表的表结构如下:

三张表的结构如下:

-- 例题1(隐式内连接)
select e.name, e.age, e.job, d.name
from emp e,
     dept d
where e.dept_id = d.id;


-- 例题2(显式内连接)
select e.name, e.age, e.job, d.name
from emp e
         inner join dept d on e.dept_id = d.id
where e.age < 30;


-- 例题3(结果要去重)
select distinct d.id, d.name
from dept d
         inner join emp e on d.id = e.dept_id;


-- 例题4(左外连接)
select e.*, d.name
from emp e
         left outer join dept d on e.dept_id = d.id
where e.age > 40;


-- 例题5
# 隐式内连接
select e.name, sg.grade
from salgrade sg,
     emp e
where e.salary between sg.losal and sg.hisal;

# 显式内连接
select e.name, sg.grade
from salgrade sg
         inner join emp e on e.salary between sg.losal and sg.hisal;


-- 例题6
select e.*, sg.grade
from emp e,
     salgrade sg
where e.dept_id = (select id from dept d where d.name = '研发部')
  and e.salary between sg.losal and sg.hisal;


-- 例题7
# 方式一
select avg(e.salary)
from emp e
where e.dept_id = (select d.id from dept d where d.name = '研发部');

# 方式二
select avg(e.salary)
from emp e,
     dept d
where e.dept_id = d.id
  and d.name = '研发部';


-- 例题8
select *
from emp
where salary > (select salary from emp where name = '灭绝');


-- 例题9
select *
from emp
where salary > (select avg(salary) from emp);


-- 例题10(放在where位置的子查询)
select e1.*
from emp e1
where e1.salary < (select avg(e2.salary)
                   from emp e2
                   where e1.dept_id = e2.dept_id);


-- 例题11(放在select位置的子查询)
select d.id,
       d.name,
       (select count(e.id)
        from emp e
        where e.dept_id = d.id) '部门员工数量'
from dept d;


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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机基础(2)——冯诺依曼体系结构

&#x1f497;计算机基础系列文章&#x1f497; &#x1f449;&#x1f340;计算机基础&#xff08;1&#xff09;——计算机的发展史&#x1f340;&#x1f449;&#x1f340;计算机基础&#xff08;2&#xff09;——冯诺依曼体系结构&#x1f340;&#x1f449;&#x1f34…

LeetCode-day02-3067. 在带权树网络中统计可连接服务器对数目

LeetCode-day02-3067. 在带权树网络中统计可连接服务器对数目 题目描述示例示例1&#xff1a;示例2: 思路代码 题目描述 给你一棵无根带权树&#xff0c;树中总共有 n 个节点&#xff0c;分别表示 n 个服务器&#xff0c;服务器从 0 到 n - 1 编号。同时给你一个数组 edges &a…

11 - 员工奖金(高频 SQL 50 题基础版)

11- 员工奖金 -- join和left join的区别 -- 如果是join则右侧的数据有的就插&#xff0c;没的就啥也不干&#xff0c;交白卷&#xff0c;也不留null -- 但是left join让右侧数据在没有对应数据时补上了null select e.name,b.bonus from Employee e left join bonus b on e.empI…

【设计模式】结构型-组合模式

前言 在软件开发中&#xff0c;设计模式是一种被广泛应用的解决问题的方法论。其中&#xff0c;结构性设计模式是一类特别重要的模式&#xff0c;它们用于处理类或对象之间的组合关系&#xff0c;其中之一就是组合模式。组合模式允许客户端统一对待单个对象和对象的组合&#…

新手小白怎么学习接口自动化测试?

接口自动化测试是一种重要的测试技术&#xff0c;对于新手小白来说&#xff0c;学习这个技术需要一定的时间和耐心。在本文中&#xff0c;我将从零开始&#xff0c;详细而规范地介绍如何学习接口自动化测试。 1. 接口自动化测试的基础知识 在开始学习接口自动化测试之前&…

【教学类-13-05】20240604《数字色块图-5*7*8-A4横板-横切》中4班

背景需求&#xff1a; 【教学类-13-04】20230404《数字色块图判断密码是否正确-5*7*8-A4横板-横切》&#xff08;中班主题《我爱我家》)_图案密码色块-CSDN博客文章浏览阅读530次。【教学类-13-04】20230404《数字色块图判断密码是否正确-5*7*8-A4横板-横切》&#xff08;中班主…

270 基于matlab的模糊自适应PID控制

基于matlab的模糊自适应PID控制&#xff0c;具有10页报告。传统PID在对象变化时&#xff0c;控制器的参数难以自动调整。将模糊控制与PID控制结合&#xff0c;利用模糊推理方法实现对PID参数的在线自整定。使控制器具有较好的自适应性。使用MATLAB对系统进行仿真&#xff0c;结…

Python采集数据处理:利用Pandas进行组排序和筛选

概述 在现代数据处理和分析中&#xff0c;网络爬虫技术变得越来越重要。通过网络爬虫&#xff0c;我们可以自动化地从网页上收集大量的数据。然而&#xff0c;如何高效地处理和筛选这些数据是一个关键问题。本文将介绍如何使用Python的Pandas库对采集到的数据进行组排序和筛选…

安徽某高校数据挖掘作业4-5 (与一些碎碎念)

1. 编写程序求函数、、的极限。 解答&#xff1a; import sympy as sp# 定义符号变量 x x sp.symbols(x)# 定义函数 f1 sp.sin(20 * x) / x f2 (1 4 * x)**(2 / x) f3 (1 4 / x)**(2 * x)# 计算极限 limit1 sp.limit(f1, x, 0) limit2 sp.limit(f2, x, 0) limit3 sp…

测绘GIS和遥感领域比较好的公众号有哪些

测绘GIS和遥感领域&#xff0c;微信公众号作为信息传播和知识分享的重要渠道&#xff0c;为从业者提供了一个快速获取行业动态、技术进展和职业发展机会的平台。分享一些在测绘GIS和遥感领域表现突出的公众号推荐&#xff1a; 1. 慧天地&#xff1a;慧天地是一个知名的测绘公众…

倪师哲学。把智慧和时间都用在学习知识上

大家好&#xff0c;今天我们接着聊倪海厦老师的思想&#xff0c;一共整理出来了6点&#xff0c;之前4点已经讲过&#xff0c;今天我们讲第五点&#xff0c;这个呢也是倪老师的原话&#xff0c;不要浪费时间去做无谓的事情&#xff0c;把智慧和时间都用在学习知识上面。 其实啊现…

每天坚持写java锻炼能力---第一天(6.4)

今天的目标是菜单&#xff1a; B站/马士兵的项目菜单 package java1;import java.util.Scanner;public class Test {public static void main(String[] args) {while(true){ //3.加入死循环&#xff0c;让输入一直有System.out.println();System.out.println("--->项…

冯喜运:6.5黄金原油今日行情趋势分析及操作策略

【黄金消息面分析】&#xff1a;在全球经济的波动中&#xff0c;美元和黄金市场的表现一直是投资者关注的焦点。最近&#xff0c;市场情绪和经济数据的波动对这两个市场产生了显著的影响。周二欧市早盘&#xff0c;现货黄金价格出现短线回调&#xff0c;金价跌破2340美元/盎司&…

Pycharm创建Conda虚拟环境时显示CondaHTTPErOT

原因&#xff1a;conda源出问题了&#xff0c;之前可以用&#xff0c;现在报错。 最好的解决方案&#xff1a;找到conda源&#xff0c;换源即可。 步骤&#xff1a; 1.修改 .condarc 文件&#xff08;文件的位置在&#xff1a;C:\Users\(你的用户名)\.condarc&#xff09;&a…

.NET IoC 容器(三)Autofac

目录 .NET IoC 容器&#xff08;三&#xff09;AutofacAutofacNuget 安装实现DI定义接口定义实现类依赖注入 注入方式构造函数注入 | 属性注入 | 方法注入注入实现 接口注册重复注册指定参数注册 生命周期默认生命周期单例生命周期每个周期范围一个生命周期 依赖配置Nuget配置文…

AIGIS地图智能体功能预览——最强WebGIS打工人秒上岗

目录 前言1.这地图智能体是用来干什么的&#xff1f;2.智能体介绍3.二维效果4.三维效果5.大模型写不出来正确的代码怎么办&#xff1f;6.所以最终会产生一个什么样的现象&#xff1f;7.现在我们可用的大模型有哪些&#xff1f;8.不会写代码怎么开发自己的专属智能体&#xff1f…

处理无法拉取GitHub库的解决方案

提交和拉取github上的库总是失败&#xff0c;这里记录一下如何使用代理解决。 首先找到端口&#xff0c;记住它的端口 然后使用git命令 # HTTP/HTTPS 协议 git config ––global http.url.proxy http://127.0.0.1:port # 以 Github 为例 git config ––global http.https:/…

解决MyBatis的N+1问题

解决MyBatis的N1问题 N1问题通常出现在一对多关联查询中。当我们查询主表数据&#xff08;如订单&#xff09;并希望获取关联的从表数据&#xff08;如订单的商品&#xff09;时&#xff0c;如果每获取一条主表记录都要执行一次从表查询&#xff0c;就会产生N1次查询的问题。假…

线性电源运放驱动调整管的方案仿真

群里有人的电路板做出来电压不稳&#xff0c;加负载就掉电压。我对这个运放的工作状态不是很理解&#xff0c;所以仿真了一下。结果却是稳定的。他用12v给运放供电&#xff0c;要求输出10.5. 从仿真看。12运放供电只能输出9v。而且还是到了运放的极限。所以通过仿真后确定怀疑路…

10-Django项目--Ajax请求

目录 Ajax请求 简单示范 html 数据添加 py文件 html文件 demo_list.html Ajax_data.py 图例 Ajax请求 简单示范 html <input type"button" id"button-one" class"btn btn-success" value"点我"> ​ ​ <script>/…