tags: 知识拓展
categories: MySQL
top: false
copyright: true
abbrlink: 1643719980
description: 在实际开发中,大部分的情况下都不是从单表中查询数据,一般都是多张表联合查询取出最终的结果。在实际开发中,一般一个业务都会对应多张表,比如:学生和班级,起码两张表。
查询结果
关于查询结果集的去重?(distinct关键字去除重复记录)
mysql> select distinct job from emp;
±----------+
| job |
±----------+
| CLERK |
| SALESMAN |
| MANAGER |
| ANALYST |
| PRESIDENT |
±----------+
select ename,distinct job from emp;
以上的sql语句是错误的。
记住:distinct只能出现在所有字段的最前面。
mysql> select distinct deptno,job from emp order by deptno;
±-------±----------+
| deptno | job |
±-------±----------+
| 10 | CLERK |
| 10 | MANAGER |
| 10 | PRESIDENT |
| 20 | ANALYST |
| 20 | CLERK |
| 20 | MANAGER |
| 30 | CLERK |
| 30 | MANAGER |
| 30 | SALESMAN |
±-------±----------+
案例:统计岗位的数量?
mysql> select count(distinct job) from emp;**
±--------------------+
| count(distinct job) |
±--------------------+
| 5 |
±--------------------+
1 row in set (0.00 sec)
连接查询
什么是连接查询?
在实际开发中,大部分的情况下都不是从单表中查询数据,一般都是多张表联合查询取出最终的结果。
在实际开发中,一般一个业务都会对应多张表,比如:学生和班级,起码两张表。
在实际上数据会存在大量的重复,导致数据的冗余。
连接查询的分类
根据语法出现的年代来划分的,包括:
SQL 92(一些老的DBA可能还在使用这种语法。DBA:Database Administrator)
SQL 99(比较新的语法)
根据表的连接方式来划分,包括:
- 内连接:
等值连接
非等值连接
自连接 - 外连接:
左外连接(左连接)
右外连接(右连接) - 全连接(很少用)
在表的连接查询方面有一种现象被称为:笛卡尔积现象
案例:找出每一个员工的部门名称,要求显示员工名和部门名
mysql> select ename,deptno from emp;
±-------±-------+
| ename | deptno |
±-------±-------+
| SMITH | 20 |
| ALLEN | 30 |
| WARD | 30 |
| JONES | 20 |
| MARTIN | 30 |
| BLAKE | 30 |
| CLARK | 10 |
| SCOTT | 20 |
| KING | 10 |
| TURNER | 30 |
| ADAMS | 20 |
| JAMES | 30 |
| FORD | 20 |
| MILLER | 10 |
±-------±-------+mysql> select * from dept
-> ;
±-------±-----------±---------+
| DEPTNO | DNAME | LOC |
±-------±-----------±---------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |select ename,dname from emp,dept;
mysql> select ename,dname from emp,dept;//ename和dname要联合起来一块显示,黏到一块。
±-------±-----------+
| ename | dname |
±-------±-----------+
| SMITH | ACCOUNTING |
| SMITH | RESEARCH |
| SMITH | SALES |
| SMITH | OPERATIONS |
| ALLEN | ACCOUNTING |
| ALLEN | RESEARCH |
| ALLEN | SALES |
| ALLEN | OPERATIONS |
| WARD | ACCOUNTING |
| WARD | RESEARCH |
| WARD | SALES |
| WARD | OPERATIONS |
| JONES | ACCOUNTING |
| JONES | RESEARCH |
| JONES | SALES |
| JONES | OPERATIONS |
| MARTIN | ACCOUNTING |
| MARTIN | RESEARCH |
| MARTIN | SALES |
| MARTIN | OPERATIONS |
| BLAKE | ACCOUNTING |
| BLAKE | RESEARCH |
| BLAKE | SALES |
| BLAKE | OPERATIONS |
| CLARK | ACCOUNTING |
| CLARK | RESEARCH |
| CLARK | SALES |
| CLARK | OPERATIONS |
| SCOTT | ACCOUNTING |
| SCOTT | RESEARCH |
| SCOTT | SALES |
| SCOTT | OPERATIONS |
| KING | ACCOUNTING |
| KING | RESEARCH |
| KING | SALES |
| KING | OPERATIONS |
| TURNER | ACCOUNTING |
| TURNER | RESEARCH |
| TURNER | SALES |
| TURNER | OPERATIONS |
| ADAMS | ACCOUNTING |
| ADAMS | RESEARCH |
| ADAMS | SALES |
| ADAMS | OPERATIONS |
| JAMES | ACCOUNTING |
| JAMES | RESEARCH |
| JAMES | SALES |
| JAMES | OPERATIONS |
| FORD | ACCOUNTING |
| FORD | RESEARCH |
| FORD | SALES |
| FORD | OPERATIONS |
| MILLER | ACCOUNTING |
| MILLER | RESEARCH |
| MILLER | SALES |
| MILLER | OPERATIONS |
±-------±-----------+
56 rows in set (0.00 sec)
笛卡尔积现象:当两张表进行连接查询的时候,没有任何条件进行限制,最终的查询结果条数两张表记录条数的乘积。
关于表的别名:
select e.ename, d.dname from emp e, dept d;
表的别名有什么好处
第一:执行效率高
第二:可读性好
怎么避免笛卡尔积现象?
思考:避免了笛卡尔积现象,会减少记录的匹配次数吗?
不会,次数还是56此。只不过显示的是有效记录
案例:找出每一个员工的部门名称,要求显示员工名和部门名。
mysql> select e.ename,d.dname from emp e, dept d where e.deptno=d.deptno;
±-------±-----------+
| ename | dname |
±-------±-----------+
| SMITH | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| JONES | RESEARCH |
| MARTIN | SALES |
| BLAKE | SALES |
| CLARK | ACCOUNTING |
| SCOTT | RESEARCH |
| KING | ACCOUNTING |
| TURNER | SALES |
| ADAMS | RESEARCH |
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
±-------±-----------+
14 rows in set (0.00 sec)
内连接之等值连接
特点:条件是等量关系
案例:查询每个员工的部门名称,要求显示员工名和部门名
SQL92:(太老,不用了)
select e.ename, d.dname from emp e, dept d where e.deptno = d.deptno;
SQL99:(常用的)
select
e.ename, d.dname
from
emp e
join
dept d
**on **
e.deptno = d.deptno; //等值连接select
e.ename, d.dname
from
emp e
inner join // inner可省略
dept d
**on **
e.deptno = d.deptno; //等值连接
SQL99语法结构更清晰一些:表的连接条件和后来的where条件分离了
内连接之非等值连接
最大的特点是:连接条件中的关系是非等量关系。
案例:找出每个员工的工资等级,要求显示员工名、工资、工资等级。
select
e.ename, e.sal, s.grade
from
emp e
join salgrade s
on
e.sal>=losal and e.sal<=hisal;±-------±--------±------+
| ename | sal | grade |
±-------±--------±------+
| SMITH | 800.00 | 1 |
| ALLEN | 1600.00 | 3 |
| WARD | 1250.00 | 2 |
| JONES | 2975.00 | 4 |
| MARTIN | 1250.00 | 2 |
| BLAKE | 2850.00 | 4 |
| CLARK | 2450.00 | 4 |
| SCOTT | 3000.00 | 4 |
| KING | 5000.00 | 5 |
| TURNER | 1500.00 | 3 |
| ADAMS | 1100.00 | 1 |
| JAMES | 950.00 | 1 |
| FORD | 3000.00 | 4 |
| MILLER | 1300.00 | 2 |
±-------±--------±------+
14 rows in set (0.00 sec)
内连接之自连接
最大的特点:一张表看做两张表。自己连接自己。
案例:找出每个员工的上级领导,要求显示员工名和对应的领导名。
select
a.ename, b.ename
from
emp a
inner join
emp b
on
a.mgr=b.deptno;
外连接
什么是外连接,和内连接有什么区别?
内连接:假设A和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接。
AB两张表没有主副之分,两张表是平等的。
外连接:假设A和B表进行连接,使用外连接的话,AB两张表中有一张表是主表,一张表是副表,主要查询主表中的数据,捎带着查询副表,当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配。
外连接的分类?
左外连接(左连接):表示左边的这张表是主表。
右外连接(右连接):表示右边的这张表是主表。
左连接有有连接的写法,右连接也会有对应左连接的写法
案例:找出每个员工的上级领导?(所有员工必须全部查询出来)
//inner可以省略
内连接
select a.ename, b.ename from emp a inner join emp b on a.mgr=b.empno;//outer可以省略
外连接(左连接)
select a.ename, b.ename from emp a left outer join emp b on a.mgr=b.empno;外连接(右连接)
select a.ename, b.ename from emp b right outer join emp a on a.mgr=b.empno;
外连接重要的特点是:主表的数据无条件的全部查询出来
案例:找出那个部门没有员工?
mysql> select d. from emp e right join dept d on e.deptno=d.deptno where e.empno is null;*
±-------±-----------±-------+
| DEPTNO | DNAME | LOC |
±-------±-----------±-------+
| 40 | OPERATIONS | BOSTON |
±-------±-----------±-------+
1 row in set (0.00 sec)
三张表怎么连接查询?
案例:找出每一个员工的部门名称以及工资等级
//全部员工
select * from emp;
//部门名称
select e.ename, d.dname from emp e join dept d on e.deptno=d.deptno;
//工资等级
select e.ename, s.grade from emp e join salgrade s on e.sal between losal and hisal;
//最终结合
select e.ename, d.dname, s.grade from emp e join dept d on e.deptno=d.deptno join salgrade s on e.sal between losal and hisal;
案例:找出每个员工的部门名称、工资等级、以及上级领导。
select e.ename, d.dname, s.grade,b.ename from emp e join dept d on e.deptno=d.deptno join salgrade s on e.sal between losal and hisal join emp b on e.mgr=b.empno;