• MySQL --- 多表查询 - 七种JOINS实现、集合运算、多表查询练习


    七种JOINS实现

    左上图的JOIN是左外连接,右上图的JOIN是右外连接,中间图的JOIN是内连接,左中图的JOIN在左上图的基础上再去掉中间重复的,只需要 A 在 B 中没有的部分,右中图的JOIN在右上图的基础上再去掉中间重复的,只需要 B 在 A 中没有的部分,左下角是全外连接

    1. -- 左上 左外连接
    2. SELECT * FROM
    3. emp LEFT JOIN dept
    4. ON emp.deptno=dept.deptno;

    1. -- 右上 右外连接
    2. SELECT * FROM
    3. emp RIGHT JOIN dept
    4. ON emp.deptno=dept.deptno;

    1. -- 左中 在左外连接的基础上
    2. SELECT * FROM
    3. emp LEFT JOIN dept
    4. ON emp.deptno=dept.deptno
    5. -- 去掉满足连接条件的记录→只需要不满足条件的→连接条件不匹配或者为NULL
    6. WHERE emp.deptno IS NULL;

    1. -- 右中 在右外连接的基础上
    2. SELECT * FROM
    3. emp RIGHT JOIN dept
    4. ON emp.deptno=dept.deptno
    5. -- 去掉满足连接条件的记录→只需要不满足条件的→连接条件不匹配或者为NULL
    6. WHERE emp.deptno IS NULL;

    全外连接可以使用以上的两张图片拼接而成,一共有 3 种方式可以实现

    接下来用左上图和右中图来实现全外连接

    1. -- 左上 左外连接
    2. SELECT * FROM
    3. emp LEFT JOIN dept
    4. ON emp.deptno=dept.deptno -- 去掉;
    5. UNION -- 求并集
    6. -- 右中 在右外连接的基础上
    7. SELECT * FROM
    8. emp RIGHT JOIN dept
    9. ON emp.deptno=dept.deptno
    10. -- 去掉满足连接条件的记录→只需要不满足条件的→连接条件不匹配或者为NULL
    11. WHERE emp.deptno IS NULL;

    使用右上图和左中图来实现全外连接

    1. -- 右上 右外连接
    2. SELECT * FROM
    3. emp RIGHT JOIN dept
    4. ON emp.deptno=dept.deptno -- 去掉;
    5. UNION -- 求并集
    6. -- 左中 在左外连接的基础上
    7. SELECT * FROM
    8. emp LEFT JOIN dept
    9. ON emp.deptno=dept.deptno
    10. -- 去掉满足连接条件的记录→只需要不满足条件的→连接条件不匹配或者为NULL
    11. WHERE emp.deptno IS NULL;

    右下图是在全连接的基础上去掉中间部分,或者用左中图和右中图拼接

    1. -- 右下图用左中图和右中图拼接
    2. -- 左中 在左外连接的基础上
    3. SELECT * FROM
    4. emp LEFT JOIN dept
    5. ON emp.deptno=dept.deptno
    6. -- 去掉满足连接条件的记录→只需要不满足条件的→连接条件不匹配或者为NULL
    7. WHERE emp.deptno IS NULL -- 去掉;
    8. UNION
    9. -- 右中 在右外连接的基础上
    10. SELECT * FROM
    11. emp RIGHT JOIN dept
    12. ON emp.deptno=dept.deptno
    13. -- 去掉满足连接条件的记录→只需要不满足条件的→连接条件不匹配或者为NULL
    14. WHERE emp.deptno IS NULL;

    补充

    1. -- 内连接
    2. -- 隐式内连接
    3. SELECT *
    4. FROM emp,dept
    5. WHERE emp.deptno=dept.deptno;
    6. -- 显示内连接 语法不同
    7. SELECT *
    8. FROM emp INNER JOIN dept
    9. ON emp.deptno=dept.deptno;
    10. -- 使用USING来关联相同的字段
    11. SELECT *
    12. FROM emp JOIN dept
    13. USING(deptno);

    自连接:一张表做等值查询,把一张表当做两张表查询

    1. -- 自连接 由于两张表名一样 所以只能取别名
    2. SELECT *
    3. FROM emp e, emp m
    4. -- 对应的领导信息
    5. WHERE e.mgr=m.empno;

    1. -- 自连接 由于两张表名一样 所以只能取别名
    2. SELECT e.empno,e.ename,m.ename 领导
    3. FROM emp e,emp m
    4. -- 对应的领导信息
    5. WHERE e.mgr=m.empno;

    集合运算

    MySQL只支持并集运算。

    并集即两个集合所有部分

     

    UNION DISTINCT

    1. 会删除重复行

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

    A={A,B,C},B={C,D,E}

    UNION DISTINCT C={A,B,C,D,E},有两个 C,重复的 C 只保留一个

    1. SELECT * FROM emp
    2. UNION
    3. SELECT * FROM emp WHERE deptno=10;

    部门编号为 10 有 3 条记录

    整个表有 15 条记录

    求并集有 15 条记录,UNION 后面不加默认为 DISTINCT

    UNION ALL

    1. 不会删除重复行

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

    A={A,B,C},B={C,D,E}

    UNION ALL C={A,B,C,C,D,E},会保留重复的

    1. SELECT * FROM emp
    2. UNION ALL
    3. SELECT * FROM emp WHERE deptno=10;

    求并集,保留重复的,共 15 + 3 = 18 条

    要求

    (1)输入的查询不能包含ORDER BY字句,可以为整个集合运算结果选择性地增加一个ORDER BY字句

    1. SELECT * FROM emp
    2. UNION ALL
    3. SELECT * FROM emp WHERE deptno=10
    4. -- 按姓名查询 对整个临时表排序而不是对emp表排序
    5. ORDER BY ename;

    MySQL --- 数据库查询 - 排序查询、分页查询

    错误用法

    1. SELECT * FROM emp ORDER BY emp.job
    2. UNION ALL
    3. SELECT * FROM emp WHERE deptno=10;

    (2)两个查询必须包含相同的列数

    第一个表只有 1 列,第二个表的列数正常

    1. SELECT emp.empno FROM emp
    2. UNION ALL
    3. SELECT * FROM emp WHERE deptno=10;

    (3)相应列必须具有兼容的数据类型。兼容个的数据类型:优先级较低的数据类型必须能隐式地转换为较高级的数据类型。比如输入的查询1的第一列为int类型,输入的查询2的第一列为float类型,则较低的数据类型int类型可以隐式地转换为较高级float类型。如果输入的查询1的第一列为char类型,输入的查询2的第一列为datetime类型,则会提示转换失败:从字符串转换日期和/或时间时,转换失败

    (4)集合运算结果中列名由输入的查询1决定,如果要为结果分配结果列,应该在输入的查询1中分配相应的别名

    1. SELECT emp.empno,emp.ename FROM emp
    2. UNION ALL
    3. SELECT emp.empno 'id',emp.ename 'name' FROM emp WHERE deptno=10;

    第一种情况在输入的查询2取别名,结果没有改变

    1. SELECT emp.empno 'id',emp.ename 'name' FROM emp
    2. UNION ALL
    3. SELECT emp.empno,emp.ename FROM emp WHERE deptno=10;

    第二种情况在输入的查询1取别名,结果改变

    (5)集合运算时,对行进行比较时,集合运算认为两个NULL相等

    多表查询练习

    1. 查询出雇佣日期在1981年的所有员工的编号、姓名、雇佣日期、工作、领导姓名、雇佣月工资、雇佣年工资(基本工资+奖金),工资等级、部门编号、部门名称、部门位置,并且求这些员工的月基本工资在1500~3500之间,将最后的结果按照年工资的降序排列,如果年工资相等,则按照工作进行排序。

    需求很多,逐步分析

    • 确定所需要的数据表

      • emp:编号、姓名、雇佣日期,工作、月工资、年薪

      • emp:领导姓名

      • dept:部门编号、名称、位置

      • salgrade:工资等级

    • 确定一致的关联字段

      • 员工和领导:e.mgr=e1.empno

      • 员工和部门:e.deptno=dept.deptno

      • 员工和工资等级:e.sal BETWEEN s.losal AND s.hisal

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

    奖金有空的部分,年薪最后的结果为空,需要判断奖金为空,就把它变成0

    1. #获取1981年入职员工的信息并且满足薪资在1500~3500之间
    2. SELECT e.empno,e.ename,e.hiredate,e.sal,(e.sal+IFNULL(e.comm,0))*12 年薪
    3. FROM emp e
    4. WHERE e.sal BETWEEN 1500 AND 3500;

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

    1. -- 获取1981年入职员工的信息并且满足薪资在1500~3500之间
    2. SELECT e.empno,e.ename,e.hiredate,e.sal,(e.sal+IFNULL(e.comm,0))*12 年薪,
    3. m.ename 领导
    4. FROM emp e,emp m
    5. WHERE e.sal BETWEEN 1500 AND 3500
    6. -- 获取领导姓名
    7. AND e.mgr=m.empno;

     步骤三:加入部门信息

    1. -- 获取1981年入职员工的信息并且满足薪资在1500~3500之间
    2. SELECT e.empno,e.ename,e.hiredate,e.sal,(e.sal+IFNULL(e.comm,0))*12 年薪,
    3. m.ename 领导,d.deptno,d.dname,d.loc
    4. FROM emp e,emp m,dept d
    5. WHERE e.sal BETWEEN 1500 AND 3500
    6. -- 获取领导姓名
    7. AND e.mgr=m.empno
    8. -- 加入部门信息
    9. AND e.deptno=d.deptno;

    步骤四:加入工资等级

    1. -- 获取1981年入职员工的信息并且满足薪资在1500~3500之间
    2. SELECT e.empno,e.ename,e.hiredate,e.sal,(e.sal+IFNULL(e.comm,0))*12 年薪,
    3. m.ename 领导,d.deptno,d.dname,d.loc,s.grade 工资等级
    4. FROM emp e,emp m,dept d,salgrade s
    5. WHERE e.sal BETWEEN 1500 AND 3500
    6. -- 获取领导姓名
    7. AND e.mgr=m.empno
    8. -- 加入部门信息
    9. AND e.deptno=d.deptno
    10. -- 加入工资等级
    11. AND e.sal BETWEEN s.losal AND s.hisal;

    步骤五:排序

    最后的结果按照年工资的降序排列,如果年工资相等,则按照工作进行排序。

    1. -- 获取1981年入职员工的信息并且满足薪资在1500~3500之间
    2. SELECT e.empno,e.ename,e.hiredate,e.job,e.sal,(e.sal+IFNULL(e.comm,0))*12 年薪,
    3. m.ename 领导,d.deptno,d.dname,d.loc,s.grade 工资等级
    4. FROM emp e,emp m,dept d,salgrade s
    5. WHERE e.sal BETWEEN 1500 AND 3500
    6. -- 获取领导姓名
    7. AND e.mgr=m.empno
    8. -- 加入部门信息
    9. AND e.deptno=d.deptno
    10. -- 加入工资等级
    11. AND e.sal BETWEEN s.losal AND s.hisal
    12. -- 排序
    13. ORDER BY 年薪 DESC,e.job ASC;

  • 相关阅读:
    计算机组成原理(三)
    Roaring Bitmap 更好的位图压缩算法
    C# 使用 RSA 加密算法生成证书签名产生“The system cannot find the file specified”异常
    Tensorboard安装及简单使用
    webpack5 eslint插件使用
    nginx错误:unknown directive “锘? in F:\nginx/conf/nginx.conf:3
    对京东云鼎的学习笔记
    使用python操作mysql,,SQL注入问题, 视图, 触发器 ,事务(掌握重点), 存储过程,索引 问题
    chrome控制台怎么看hover的样式
    Leetcode刷题详解——将x减到0的最小操作数
  • 原文地址:https://blog.csdn.net/weixin_60569662/article/details/125849203