七种JOINS实现

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

-- 左上 左外连接
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
-- 去掉满足连接条件的记录→只需要不满足条件的→连接条件不匹配或者为NULL
WHERE emp.deptno IS NULL;

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

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

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

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

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

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

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

-- 右下图用左中图和右中图拼接
-- 左中 在左外连接的基础上
SELECT * FROM
emp LEFT JOIN dept
ON emp.deptno=dept.deptno
-- 去掉满足连接条件的记录→只需要不满足条件的→连接条件不匹配或者为NULL
WHERE emp.deptno IS NULL -- 去掉;
UNION
-- 右中 在右外连接的基础上
SELECT * FROM
emp RIGHT JOIN dept
ON emp.deptno=dept.deptno
-- 去掉满足连接条件的记录→只需要不满足条件的→连接条件不匹配或者为NULL
WHERE emp.deptno IS NULL;

补充

USING 指定条件,等值条件的两个字段都是一模一样的,既然是一模一样的,能不能只写一个字段呢?答案是肯定的,USING 可以让 MySQL 自己在表中找这个字段给我们建立关联

-- 内连接
-- 隐式内连接
SELECT *
FROM emp,dept
WHERE emp.deptno=dept.deptno;-- 显式内连接 语法不同
SELECT *
FROM emp INNER JOIN dept
ON emp.deptno=dept.deptno;-- 使用USING来关联相同的字段
SELECT *
FROM emp JOIN dept
USING(deptno);

自连接:一张表做等值查询,把一张表作为两张表做等值查询,由于字段不一样,所以不能使用 USING

每一个员工都有领导编号 mgr,领导的信息也在这张表当中

-- 自连接 由于两张表名一样 只能通过取别名区分SELECT *
FROM emp e, emp m
-- 对应的领导信息
WHERE e.mgr=m.empno;

-- 自连接 由于两张表名一样 只能通过取别名区分SELECT e.empno,e.ename,m.ename 领导
FROM emp e,emp m
-- 对应的领导信息
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 只保留一个

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

整个表有 15 条记录

部门编号为 10 有 3 条记录

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

UNION ALL

  1. 不会删除重复行

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

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

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

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

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

要求

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

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

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

错误用法

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

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

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

第一个表只有 1 列

第二个表的列数正常

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

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

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

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

SELECT emp.empno 'id',emp.ename 'name' FROM emp
UNION ALL
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

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

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

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

步骤三:加入部门信息

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

步骤四:加入工资等级

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

步骤五:排序

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

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

MySQL --- 多表查询 - 七种JOINS实现、集合运算、多表查询练习相关推荐

  1. MySQL的两张表的七种Join查询

    SQL的语法格式如下 SELECT DISTINCT< select_list > FROM< left_table > < join_type > JOIN &l ...

  2. MySQL复合索引中七种常见的索引失效情形

    #数据库说明 使用的table emp如下: CREATE TABLE emp(id INT(11) NOT NULL AUTO_INCREMENT,empno INT NOT NULL,NAME V ...

  3. mysql修改表名几种方式_Oracle数据库中修改表名的几种方式

    Oracle数据库中修改表名的几种方式如下:answer1: ALTER TABLE old_table_name RENAME TO new_table_name;(大写为系统命令)answer2: ...

  4. Gridview数据控件的七种字段类型

    9.8  数据控件的七种字段类型(Fields Type)的应用 GridView共支持七种字段类型,字段原本应该叫"Column"比较恰当,但ASP.NET 2.0却采用另一个名 ...

  5. Hive创建表的几种方式

    hive执行的三种方式: 1. 用hive CLI 2. 终端执行hive命令: hive -e hive语句 3. 终端执行hive脚本: hive -f  hive脚本 如果需要通过jdbc来连接 ...

  6. 318分组聚合,关联查询(多表连接查询)(连接查询),连接查询oracle写法,集合运算ld

    ----------分组聚合:对表里面的数据进行各个维度/角度的统计 -------------统计:需要用 聚合函数 max(目标字段):求最大值 min(目标字段) :求最小值 avg(目标字段) ...

  7. Excel数据分析(七)第六章数据透视表

    1.原始数据的处理方法 (1)所有数据都要汇总在一张表当中 (2)只有一维表才能建立数据透视表(一维表是指表的第一行是字段名,下面是对应的数据) (3)表中不能有空值,如果没有数据建议填入0. (4) ...

  8. vue实现input输入模糊查询(三种方式)

    vue实现input输入模糊查询(三种方式) 目录 vue实现input输入模糊查询(三种方式) 1 计算属性实现模糊查询 演示: 2 watch 监听实现模糊查询 3 通过按钮点击实现模糊查询 演示 ...

  9. 算法补天系列之有序表的四种实现方式——AVL树,SB树,红黑树,跳表(重点)介绍说明

    有序表(MAP):除了支持哈希表所有操作之外,是有序组织的,可以知道排序的. 其实红黑树,AVL,SB数,跳表这四种结构都可以实现有序表.时间复杂度是一个级别的.一般SB树常用一些,因为结合题目修改成 ...

最新文章

  1. python 写入excel_实用小工具python数组快速写入excel表格
  2. C#——委托(delegate)DEMO
  3. URI概念的简单介绍
  4. 2018第九届蓝桥杯省赛真题 C语言B组 第一题
  5. Appium安装使用总结
  6. 数据本地存储方法封装(笔记)localStorage、sessionStorage
  7. 从 Microsoft Dynamics CRM 4.0 server迁移到 Microsoft Dynamics CRM 2013 Server
  8. 14_按类别分页展示商品
  9. IBM刀片服务器管理模块恢复出厂默认值实战
  10. [整理]WebUploader + SpringMVC 实现多文件断点续传之二 多文件断点续传
  11. composer错误Could not find package 的解决方法
  12. fpga学习——zynq图像处理中的DVP流接口封装
  13. [转载]如何用C#做一个类似于桌面插件的程序
  14. 使用x64编译fastdb报错
  15. 服务器的硬件设备及raid
  16. 为快捷方式文件(lnk文件)右键菜单添加“打开所在文件夹”
  17. ubuntu 18.04安装 vmware 15
  18. protege的下载
  19. 整理全网文档管理平台,持续跟更新
  20. 我为什么劝你不要过度纠结于技术细节?

热门文章

  1. 什么是附近推?附近推怎么投放?
  2. 路由策略(acl、IP-prefix、route-policy)
  3. 手机开机卡在android画面,手机一直停在开机画面怎么解决【图文】
  4. 微信 SHA1 签名_微信公众号自动回复功能开发
  5. 什么是RS485总线?怎么使用RS485总线?一文了解清楚
  6. 字符串的输入输出处理
  7. [web效果实现-3] 拼音排序通讯录实现
  8. rsync命令以及xsync封装
  9. C语言的va_list使用方法
  10. [翻译]Linter简介-摘自维基百科