【JavaWeb学习Day15】

Tlias智能学习系统

员工管理:

多表关系:

1.一对多

场景:部门与员工的关系(一个部门下有多个员工)

体现:需要在多的一方添加字段,关联一的一方的主键

多表问题分析:

现象:部门数据可以直接删除,然而还有部分员工归属于该部门下,此时就出现了数据的不完整、不一致问题。

原因:目前上述的两张表,在数据库层面,并未建立关联,所以是无法保证数据的一致性和完整性。

解决办法:外键约束。

外键约束的语法:

sql 复制代码
-- 创建表时指定
create table 表名(
        字段名    数据类型,
        ...
        [constraint]   [外键名称]  foreign  key (外键字段名)   references   主表 (主表列名)        
);
​
​
-- 建完表后,添加外键
alter table  表名  add constraint  外键名称  foreign key(外键字段名) references 主表(主表列名);
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);

外键约束:

物理外键:使用foreign key 定义外键关联另一张表。缺点:1.影响增、删、改的效率(需要检测外键关系)。2.仅用于单节点数据库,不适用于分布式、集群场景。3.容易引发数据库的死锁问题,消耗性能。

逻辑外键:在业务层逻辑中,解决外键关联。优点:通过逻辑外键,就可以很方便的解决上述问题。

2.多对多

案例:学生 与 课程的关系

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

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

3.一对一

案例:用户 与 身份证信息 的关系。

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

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

案例:根据页面原型以及需求文档分析并设计表结构

**1.需求:**请根据资料中提供的页面原型,设计 员工模块 涉及到的表结构。

2.步骤:

阅读页面原型以及需求文档,分析各个模块涉及到表结构,以及表结构之间的关系。

根据页面原型以及需求文档,分析各个表结构中具体的字段以及约束。

多表查询:

**1.多表查询:**指从多张表中查询数据。

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

3.连接查询:

内连接:相当于查询A、B交集部分数据。

具体实现:

sql 复制代码
-- ============================= 内连接 ==========================
-- A. 查询所有员工的ID, 姓名 , 及所属的部门名称 (隐式、显式内连接实现)
-- 隐式
select emp.id,emp.name,dept.name from dept , emp where emp.dept_id=dept.id;
-- 显式(inner可以省略)
select emp.id,emp.name,dept.name from dept inner join emp on emp.dept_id=dept.id;
select emp.id,emp.name,dept.name from dept  join emp on emp.dept_id=dept.id;
​
​
-- B. 查询 性别为男, 且工资 高于8000 的员工的ID, 姓名, 及所属的部门名称 (隐式、显式内连接实现)
-- 隐式
select emp.id,emp.name,dept.name from dept , emp where emp.dept_id=dept.id and emp.gender=1 and emp.salary>8000;
-- 显式(inner可以省略)
select emp.id,emp.name,dept.name from dept  join emp on emp.dept_id=dept.id where emp.gender=1 and emp.salary>8000;
​
-- 为表起别名
select e.id,e.name,d.name from dept d join emp e on e.dept_id=d.id where e.gender=1 and e.salary>8000;

外连接:左外连接:查询左表所有数据(包括两张表交集部分数据)右外连接:查询右表所有数据(包括两张表交集部分数据)

具体实现:

sql 复制代码
-- =============================== 外连接 ============================
-- A. 查询员工表 所有 员工的姓名, 和对应的部门名称 (左外连接)
select e.name , d.name from  emp e left  outer join dept d on e.dept_id = d.id;
​
-- B. 查询部门表 所有 部门的名称, 和对应的员工名称 (右外连接)
select d.name , e.name from  emp e right  join dept d on e.dept_id = d.id;
​
-- C. 查询工资 高于8000 的 所有员工的姓名, 和对应的部门名称 (左外连接)
select e.name,d.name from emp e left join dept d on d.id = e.dept_id where e.salary>8000;

提示:对于外连接,常用的是左外连接,因为右外连接的SQL也可以改造成为左外连接(两张表调换个顺序)。

4.子查询:

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

形式:select * from t1 where column1 = (select column1 from t2 ...);

说明:子查询外部的语句可以是insert、update、delete、select的任何一个,最常见的是select。

分类:

1.标量子查询:子查询返回的结果为单个值。

2.列子查询:子查询返回的结果为一列。

3.行子查询:子查询返回的结果为一行。

4.表子查询:子查询返回的结果为多行多列。

(提示:子查询的要领是,先对需求做拆分,明确具体的步骤,然后再逐步编写SQL语句。)

sql 复制代码
-- ========================= 子查询 ================================
-- 标量子查询
-- A. 查询 最早入职 的员工信息
-- a. 获取到最早入职时间
    select min(entry_date) from emp;
-- b.查询最早入职的员工信息
    select * from emp where entry_date='2000-01-01';
​
    select * from emp where entry_date=(select min(entry_date) from emp);
-- B. 查询在 "阮小五" 入职之后入职的员工信息
-- a. 查询"阮小五"入职的时间
    select entry_date from emp where name = '阮小五';
-- b. 查询在该时间之后入职的员工信息
    select * from emp where entry_date > '2015-01-01';
​
    select * from emp where entry_date > (select entry_date from emp where name = '阮小五');
​
​
-- 列子查询
-- A. 查询 "教研部" 和 "咨询部" 的所有员工信息
-- a.查询"教研部"和"咨询部"的部门ID
    select id from dept where name='教研部' or name='咨询部';
-- b.查询指定部门ID的员工信息
    select * from emp where dept_id in (2,3);
​
    select * from emp where dept_id in (select id  from dept where name='教研部' or name='咨询部');
​
-- 行子查询
-- A. 查询与 "李忠" 的薪资 及 职位都相同的员工信息 ;
-- a. 查询 "李忠" 的薪资 及 职位
    select salary,job from emp where name = '李忠';
-- b. 查询指定薪资和职位的员工信息
    select * from emp where job = 5 and salary = 5000;
​
    select * from emp where job = (select job from emp where name = '李忠') and salary = (select salary from emp where name = '李忠');
​
-- 优化:
    select * from emp where (salary,job) = (select salary,job from emp where name = '李忠');
​
-- 表子查询
-- A. 获取每个部门中薪资最高的员工信息
-- a. 获取每个部门的最高薪资
    select dept_id,max(salary) from emp group by dept_id;
​
-- b. 查询每个部门中薪资最高的员工信息
    select * from emp e,(select dept_id,max(salary) max_salary from emp group by dept_id) a
             where e.salary = a.max_salary and e.dept_id = a.dept_id;

案例:

sql 复制代码
-- 需求:
-- 1. 查询 "教研部" 性别为 男,且在 "2011-05-01" 之后入职的员工信息 。
    select * from emp where entry_date>'2011-05-01'and id in (select id from emp where gender = 1 and dept_id = ( select id from dept where name = '教研部'));
-- 答案:
    select e.* from emp as e , dept as d where e.dept_id = d.id and d.name = '教研部' and e.gender = 1 and e.entry_date > '2011-05-01';
-- 2. 查询工资 低于公司平均工资的 且 性别为男 的员工信息 。
    select avg(salary) from emp;
    select * from emp where salary<(select avg(salary) from emp) and gender = 1;
​
-- 3. 查询部门人数超过 10 人的部门名称 。
-- 答案:
    select d.name,count(*) from emp e,dept d where e.dept_id = d.id  group by d.name having count(*)>10;
​
-- 4. 查询在 "2010-05-01" 后入职,且薪资高于 10000 的 "教研部" 员工信息,并根据薪资倒序排序。
    select * from emp where entry_date>'2010-05-01' and salary>10000
                        and dept_id=(select id from dept where name='教研部') order by salary desc ;
-- 答案:
    select * from emp e , dept d where e.dept_id = d.id and e.entry_date > '2010-05-01'
                                   and e.salary > 10000 and d.name = '教研部' order by e.salary desc;
​
-- 5. 查询工资 低于本部门平均工资的员工信息
    select dept_id,avg(salary) from emp group by dept_id;
-- 答案;
-- 5.1 查询每个部门的平均工资
    select dept_id, avg(salary) avg_sal from emp group by dept_id;
​
-- 5.2 查询工资 低于本部门平均工资 的员工信息 。
    select e.* from emp e , (select dept_id, avg(salary) avg_sal from emp group by dept_id) as a
        where e.dept_id = a.dept_id and e.salary < a.avg_sal;
相关推荐
不会Hello World的小苗11 分钟前
Java——列表(List)
java·python·list
二十七剑1 小时前
jvm中各个参数的理解
java·jvm
东阳马生架构2 小时前
JUC并发—9.并发安全集合四
java·juc并发·并发安全的集合
计算机小白一个3 小时前
蓝桥杯 Java B 组之岛屿数量、二叉树路径和(区分DFS与回溯)
java·数据结构·算法·蓝桥杯
White graces3 小时前
正则表达式效验邮箱格式, 手机号格式, 密码长度
前端·spring boot·spring·正则表达式·java-ee·maven·intellij-idea
菠菠萝宝3 小时前
【Java八股文】10-数据结构与算法面试篇
java·开发语言·面试·红黑树·跳表·排序·lru
不会Hello World的小苗3 小时前
Java——链表(LinkedList)
java·开发语言·链表
Allen Bright4 小时前
【Java基础-46.3】Java泛型通配符详解:解锁类型安全的灵活编程
java·开发语言
柃歌4 小时前
【UCB CS 61B SP24】Lecture 7 - Lists 4: Arrays and Lists学习笔记
java·数据结构·笔记·学习·算法
柃歌4 小时前
【UCB CS 61B SP24】Lecture 4 - Lists 2: SLLists学习笔记
java·数据结构·笔记·学习·算法