第六章 复合查询

第六章 复合查询

  • 一、前言
  • 二、笛卡尔积
  • 三、多表查询
    • 1、多表查询的理解
    • 2、笛卡尔积与多表拼接
    • 3、多表查询示例
      • (1)显示雇员名、雇员工资以及所在部门的名字
      • (2)显示部门号为10的部门名,员工名和工资
      • (3)显示各个员工的姓名,工资,及工资级别
  • 四、自连接
    • 1、什么是自连接
    • 2、自连接示例
      • (1)方法一:单表查询:
      • (2)方法二:多表查询:
  • 五、子查询
    • 1、什么是子查询
    • 2、单行子查询
      • 示例
    • 3、多行子查询
      • (1)in关键字
      • (2)all关键字
      • (3)any关键字
    • 4、多列子查询
      • (1)示例
    • 5、在from子句中使用子查询
      • (1)查询结果作为一张临时表
      • (2)示例
        • 显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资
        • 查找每个部门工资最高的人的姓名、工资、部门、最高工资
        • 显示每个部门的信息(部门名,编号,地址)和人员数量
    • 6、合并查询
      • (1)union
        • 作用
        • 示例:将工资大于2500或职位是MANAGER的人找出来
      • (2)union all
        • 作用
        • 示例:将工资大于25000或职位是MANAGER的人找出来

一、前言

在前面的章节中,我们介绍的是单表查询,但是在本章节中我们要讲解的是多表查询。

二、笛卡尔积

设A,B为集合,用A中元素为第一元素,B中元素为第二元素构成有序对,所有这样的有序对组成的集合叫做A与B的笛卡尔积,记作AxB.

笛卡尔积的符号化为:

A x B = < x , y > ∣ x ∈ A ∧ y ∈ B AxB={|x∈A∧y∈B} AxB=<x,y>xAyB

例如, A = a , b , B = 0 , 1 , 2 A={a,b},B={0,1,2} A=a,b,B=0,1,2,则

A x B = < a , 0 > , < a , 1 > , < a , 2 > , < b , 0 > , < b , 1 > , < b , 2 > AxB={,,,,,} AxB=<a,0>,<a,1>,<a,2>,<b,0>,<b,1>,<b,2>

B x A = < 0 , a > , < 0 , b > , < 1 , a > , < 1 , b > , < 2 , a > , < 2 , b > BxA={<0,a>,<0,b>,<1,a>,<1,b>,<2,a>,<2,b>} BxA=<0,a>,<0,b>,<1,a>,<1,b>,<2,a>,<2,b>

三、多表查询

1、多表查询的理解

当我们涉及到多表查询的时候,MySQL会将各个表格以笛卡尔积的形式进行拼接,最终拼接为一张表。 所以表面上我们是对多个表进行查询,但实际上我们依旧是在进行单表查询。

2、笛卡尔积与多表拼接

比如我们现在有两个表A和B,那么mysql在拼接的时候,会将A表中每一条语句与B表中的所有语句进行拼接。也就是说,最终会罗列出记录拼接的所有可能。

当mysql进行拼接之后,所谓的多表查询就转化为了单表查询。

但是,由于mysql罗列出了所有的拼接可能,所以在这些拼接的结果中难免会有一些不符合逻辑的记录,此时就需要我们进行适当的筛选。

3、多表查询示例

我们这里使用的是一个新的数据库:scott。
这个数据库中有三个表:dept、emp、salgrade
这三个表的描述如下:

表dept的描述:
第六章 复合查询_第1张图片
表emp的描述:
第六章 复合查询_第2张图片

表salgrade的描述:
第六章 复合查询_第3张图片

(1)显示雇员名、雇员工资以及所在部门的名字

因为上面的数据来自EMP和DEPT表,因此要联合查询。
我们先看看两个表各自的内容,再看一看两个表拼接后的内容。
emp表的内容如下:
第六章 复合查询_第4张图片
dept的内容如下:
第六章 复合查询_第5张图片
现在将两个表进行拼接,结果如下(由于拼接的结果很长,所以只展示一部分):
第六章 复合查询_第6张图片
上面这个表中有一个缺点,我们发现,表中有两列deptno,但是某些记录在这两列对应的数值并不相等。这些不相等的数据就是我们要筛选掉的。
所以我们可以用如下语句进行筛选:

select * from emp, dept where emp.deptno = dept.deptno;

这里形如:表的名称.变量名的语法格式非常像c中的结构体或者是c++中的类。
第六章 复合查询_第7张图片
当我们将表中数据进行正确的筛选后,就可以进行单表查询了。

我们刚刚的需求是:显示雇员名、雇员工资以及所在部门的名字

所以可以使用下面的语句进行筛选:

select ename, sal,dname from emp, dept where emp.deptno = dept.deptno;

第六章 复合查询_第8张图片

(2)显示部门号为10的部门名,员工名和工资

select dname,ename,sal from emp, dept where emp.deptno = dept.deptno and emp.deptno = 10;

第六章 复合查询_第9张图片

(3)显示各个员工的姓名,工资,及工资级别

select ename,sal,grade from emp, salgrade where emp.sal between salgrade.losal and salgrade.hisal;

第六章 复合查询_第10张图片

四、自连接

1、什么是自连接

自连接是指同一张表进行连接查询,即自己和自己做笛卡尔积运算。

2、自连接示例

显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号–empno)

(1)方法一:单表查询:

select empno, ename from emp where emp.empno = (select mgr from emp where ename = 'FORD');

第六章 复合查询_第11张图片

(2)方法二:多表查询:

select leader.empno, leader.ename from emp leader, emp worker where worker.mgr = leader.empno and worker.ename = 'FORD';

这里用到了给表起别名的方式。
在这里插入图片描述

五、子查询

1、什么是子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。其实我们刚刚在介绍自连接的时候, 示例中所用到的第一个方法就是子查询。

2、单行子查询

示例

显示SMITH同一部门的员工

select * from emp where deptno = (select deptno from emp where ename = 'SMITH');

第六章 复合查询_第12张图片

3、多行子查询

多行子查询即:返回多行记录的子查询。

(1)in关键字

查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的。

select ename, job, sal, deptno from emp where job in (select job from emp where deptno = 10) and deptno != 10;

第六章 复合查询_第13张图片

(2)all关键字

显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号。

select ename,sal,deptno from emp where sal > all (select sal from emp where deptno = 30);

第六章 复合查询_第14张图片

(3)any关键字

显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)

select ename, sal, deptno from emp where sal > any(select sal from emp where deptno = 30);

第六章 复合查询_第15张图片

4、多列子查询

单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询则是指查询返回多个列数据的子查询语句。

(1)示例

查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人。

select * from emp where (deptno, job) = (select deptno, job from emp where ename = 'SMITH') and ename != 'SMITH';

第六章 复合查询_第16张图片

5、在from子句中使用子查询

(1)查询结果作为一张临时表

通过前面的例子,我们发现每次我们执行一个语句后,都会出现一个新的表。那么我们就可以把这个表当作一个临时表作为后续的查询需要。

(2)示例

显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资

我们先查询一下各个部门的平均工资。形式如下图所示:
第六章 复合查询_第17张图片
现在我们将这个表作为新的表,并且给这个表起名为tmp。接下来就可以按照多表查询的方式去完成我们的题目了。

select ename, emp.deptno, sal, asal from emp,(select deptno, avg(sal) asal  from emp group by deptno)o) tmp where emp.deptno = tmp.deptno and sal > asal;

第六章 复合查询_第18张图片

查找每个部门工资最高的人的姓名、工资、部门、最高工资

select ename, sal, emp.deptno, msal from emp,(select deptno, max(sal) msal from emp group by deptno)) tmp where emp.deptno = tmp.deptno and emp.sal = msal;

第六章 复合查询_第19张图片

显示每个部门的信息(部门名,编号,地址)和人员数量

6、合并查询

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。

(1)union

作用

该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。

示例:将工资大于2500或职位是MANAGER的人找出来

select ename, sal, job from emp where sal > 2500 union  select ename, sal, job from emp where job = 'MANAGER';

第六章 复合查询_第20张图片

(2)union all

作用

该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。

示例:将工资大于25000或职位是MANAGER的人找出来

select ename, sal, job from emp where sal > 2500 union all  select ename, sal, job from emp where job = 'MANAGER';

第六章 复合查询_第21张图片

你可能感兴趣的:(MySQL,数据库,mysql)