0
点赞
收藏
分享

微信扫一扫

企业网综合配置实践

编程练习生J 2023-06-18 阅读 35

前言

目录


一、多表关系

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

✨✨一对多(多对一)

在这里插入图片描述

✨✨多对多

在这里插入图片描述

✨✨一对一

在这里插入图片描述
在这里插入图片描述

二、多表查询

在具体实现连接操作时,首先将两个或两个以上的表按照某个条件连接起来,然后再查询到所要求的数据记录

✨✨连接查询分为交叉连接,内连接,外连接查询三种方式。

1、交叉连接

✨✨交叉连接语法:

SELECT <字段名> FROM <表1> CROSS JOIN <表2> 
SELECT <字段名> FROM <表1>, <表2> 

✨✨交叉连接练习:查询员工及员工所在部门信息

SELECT * FROM emp,dept; 
SELECT * FROM emp CROSS JOIN dept; 

结果有56条,员工有14人,部门有4个,但是这样就会产出很多无效记录,特别是两张表的数据量都很大,这时候就需要消除笛卡尔积的无效记录,我们需要使用关联字段

✨✨范例:利用等值条件来处理笛卡尔积

SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno;

这样我们处理完之后就只有14条记录了,刚好一一对应

2、内连接

✨✨有两种语法,显示的和隐式的,返回连接表中符合连接条件和查询条件的数据行(所谓的连接表就是数据库在做查询形成的中间表)

  • 隐式内连接

    SELECT * FROM 表1,表2 WHERE 条件;
    
  • 显示内连接(使用关键字INNER JOIN)

    SELECT * FROM 表1 [INNER] JOIN 表2 ON 条件; 
    

等值连接:

  • 查询员工及部门信息

    #隐式连接
    SELECT * FROM emp e,dept d WHERE e.deptno=d.deptno;
    #显示连接
    SELECT * FROM emp e INNER JOIN dept d ON e.deptno=d.deptno;
    

    需要注意的是:如果指定了别名,原来的SQL表名就不可以使用了

  • 等值连接可以使用USING来自动关联两表中相同的列

    SELECT * FROM emp INNER JOIN dept USING(deptno);
    

    效果如下:

在这里插入图片描述

非等值连接:

  • 查询员工工资级别

    #隐式连接
    SELECT * FROM emp e,salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal;
    #显示连接
    SELECT * FROM emp e INNER JOIN salgrade s ON  e.sal BETWEEN s.losal AND s.hisal;
    

    效果如下:

在这里插入图片描述

自连接:

在这里插入图片描述

我们可以看上面的员工表,如果我们现在要查询每个员工对应的领导姓名,需要通过自连接

SELECT e.ename,e.mgr,me.ename 领导 FROM emp e,emp me WHERE e.mgr=me.empno;

在这里插入图片描述

3、外连接

语法:

SELECT * FROM 表1 LEFT|RIGHT|FULL [OUTER] JOIN 表2 ON 条件; 
  • 左外链接

    表关系的笛卡尔积中,出了选择相匹配的数据记录,还包含关联左边表中不匹配的数据记录。

    查询员工及对应的部门信息(没有部门的员工也显示出来,没有员工的部门不显示

    SELECT * FROM emp e LEFT OUTER JOIN dept d ON e.deptno=d.deptno;
    

    效果如下:

在这里插入图片描述

  • 右外连接

    在表关系的笛卡尔积中,出了选择相匹配的数据记录,还包含关联右边表中不匹配的数据记录。

    查询员工及对应的部门信息(没有部门的员工不显示,没有员工的部门显示

    SELECT * FROM emp e RIGHT OUTER JOIN dept d ON e.deptno=d.deptno;
    

    效果如下:

在这里插入图片描述

  • 全连接:

    在表关系的笛卡尔积中,出了选择相匹配的数据记录,还包含关联左右两边表中不匹配的数据记录。

    查询员工及对应的部门信息(没有部门的员工显示,没有员工的部门显示

    SELECT *
    FROM emp  LEFT JOIN dept
    ON emp.deptno=dept.deptno
    UNION
    SELECT *
    FROM emp  RIGHT JOIN dept
    ON emp.deptno=dept.deptno
    WHERE emp.deptno IS NULL;
    

    这个看不懂没关系,因为MySQL不支持全连接,所以我们这里用了集合运算实现的,下面会讲~

    效果如下:

在这里插入图片描述

三、集合运算

  • UNION DISTINCT

    • UNION ALL 不会删除重复行

    • 相同的行在结果中只出现一次

      SELECT * FROM emp
      UNION
      SELECT * FROM emp WHERE deptno=10;
      
  • UNION ALL:

    • UNION 会删除重复行

    • 相同的行在结果中可能出现多次

      SELECT * FROM emp
      UNION ALL
      SELECT * FROM emp WHERE deptno=10;
      

✨✨要求:

  • 输入的查询不能包含ORDER BY字句,可以为整个集合运算结果选择性地增加一个ORDER BY字句
  • 两个查询必须包含相同的列数
  • 相应列必须具有兼容的数据类型。兼容的数据类型:优先级较低的数据类型必须能隐式转换为较高级的数据类型。比如输入的查询1的第一列为int类型,输入的查询2的第一列为float类型,则较低的数据类型int类型可以隐式地转换为较高级float类型。如果输入的查询1的第一列为char类型,输入的查询2的第一列为datetime类型,则会提示转换失败:从字符串转换日期或字符串转时间时,转换失败;
  • 集合运算结果中列名由输入的查询1决定,如果要为结果分配结果列,应该在输入的查询1中分配相应的别名
  • 集合运算时,对行进行时,集合运算认为两个NULL相等

四、七种JOINS实现

在这里插入图片描述

图一就是左外连接:

SELECT *
FROM emp  LEFT JOIN dept
ON emp.deptno=dept.deptno; 

图二为右外连接:

SELECT * 
FROM emp RIGHT JOIN dept
ON emp.deptno=dept.deptno;

图三为左外连接去掉交集部分:

SELECT *
FROM emp  LEFT JOIN dept
ON emp.deptno=dept.deptno
WHERE emp.deptno IS NULL;

图四为等值连接,只要交集:

SELECT *
FROM emp e,dept d
WHERE e.deptno=d.deptno;

图五为右外连接去掉交集部分:

SELECT *
FROM emp  RIGHT JOIN dept
ON emp.deptno=dept.deptno
WHERE emp.deptno IS NULL;

图六可以可以为1,5或2,3或4,7的并集:

SELECT *
FROM emp  LEFT JOIN dept
ON emp.deptno=dept.deptno
UNION
SELECT *
FROM emp  RIGHT JOIN dept
ON emp.deptno=dept.deptno
WHERE emp.deptno IS NULL;

图七为3,5的并集:

SELECT *
FROM emp  LEFT JOIN dept
ON emp.deptno=dept.deptno
WHERE emp.deptno IS NULL
UNION
SELECT *
FROM emp  RIGHT JOIN dept
ON emp.deptno=dept.deptno
WHERE emp.deptno IS NULL;

效果如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、多表查询练习

题目:

需求很多,逐步分析

  • 确定所需要的数据表
    • emp:编号、姓名、雇佣日期,工作、月工资、年薪
    • emp:领导姓名
    • dept:部门编号、名称、位置
    • salgrade:工资等级
  • 确定一致的关联字段
    • 员工和领导:e.mgr=e1.empno
    • 员工和部门:e.deptno=dept.deptno
    • 员工和工资等级:e.sal BETWEEN s.losal AND s.hisal

✨✨步骤一:查询出所有在1981年雇佣的雇员编号、姓名、御用日期、工作、月工资、年工资,并且月薪在1500~3500之间。只需要emp单张表即可。

SELECT e.empno,e.ename,e.hiredate,e.job,e.sal,(e.sal+IFNULL(e.comm,0))*12 年薪
FROM emp e
WHERE DATE_FORMAT(e.hiredate,'%Y')='1981' AND e.sal BETWEEN 1500 AND 3500;

✨✨步骤二:加入领导信息,使用自身关联。

SELECT e.empno,e.ename,e.hiredate,e.job,me.ename 领导,e.sal,(e.sal+IFNULL(e.comm,0))*12 年薪
FROM emp e,emp me
WHERE DATE_FORMAT(e.hiredate,'%Y')='1981' AND e.sal BETWEEN 1500 AND 3500
AND e.mgr=me.empno;

✨✨步骤三:加入工资等级和部门信息

SELECT e.empno,e.ename,e.hiredate,e.job,me.ename 领导,e.sal,(e.sal+IFNULL(e.comm,0))*12 年薪,s.grade,d.deptno,d.dname,d.loc
FROM emp e,emp me,salgrade s,dept d
WHERE DATE_FORMAT(e.hiredate,'%Y')='1981' AND e.sal BETWEEN 1500 AND 3500
AND e.mgr=me.empno
AND e.sal BETWEEN s.losal AND s.hisal
AND e.deptno=d.deptno;

✨✨步骤四:排序

SELECT e.empno,e.ename,e.hiredate,e.job,me.ename 领导,e.sal,(e.sal+IFNULL(e.comm,0))*12 年薪,s.grade,d.deptno,d.dname,d.loc
FROM emp e,emp me,salgrade s,dept d
WHERE DATE_FORMAT(e.hiredate,'%Y')='1981' AND e.sal BETWEEN 1500 AND 3500
AND e.mgr=me.empno
AND e.sal BETWEEN s.losal AND s.hisal
AND e.deptno=d.deptno
ORDER BY 年薪 DESC,job ASC;

效果如下:

在这里插入图片描述

六、总结

举报

相关推荐

0 条评论