文章目录
- 1. 什么是连接查询?
- 2. 连接查询的分类
- 3. 笛卡尔积现象(笛卡尔乘积现象)
- 4. 表的别名
- 5. 怎么避免笛卡尔积现象?
1. 什么是连接查询?
在实际开发中,大部分情况下都不是从单表中查询数据,一般都是多张表联合查询出最终结果。
在实际的开发中,一般一个业务都会对应多张表,比如:学生和班级,起码两张表。
当检索数据时,通过连接操作查询出存放在多个表中的不同实体的信息。连接操作给用户带来很大的灵活性,他们可以在任何时候增加新的数据类型。为不同实体创建新的表,然后通过连接进行查询。
stuno stuname classno classname
-----------------------------------------------------------------------------------
1 zs 1 北京大兴区亦庄经济技术开发区第二中学高三1班
2 ls 1 北京大兴区亦庄经济技术开发区第二中学高三1班
...
学生和班级信息存储到一张表中,结果就像上面一样,数据会存在大量的重复,导致数据的冗余,浪费存储空间!
2. 连接查询的分类
根据语法出现的年代来划分的话可以分为:
SQL92(一些老的DBA可能还在使用这种语法。DBA:DataBase Adminstrator,数据集管理员);
SQL99(比较新的语法);
根据表的连接方式来划分,包括:
(1)内连接:
- 等值连接
- 非等值连接
- 自连接
(2)外连接
- 左外连接(左连接)
- 右外连接(右连接)
(3)全连接(这个很少用)
3. 笛卡尔积现象(笛卡尔乘积现象)
在表的连接查询方面有一种现象被称为:笛卡尔乘积现象。当两张表进行连接查询的时候,没有任何条件进行限制,最终的查询结果条数是两张表记录条数的乘积。
表A和B连接查询时,表A中一条记录都与表B中的所有记录进行匹配
我们可以通过一个案例来引出这个现象。
案例:找出每一个员工的部门名称,要求显示员工名和部门名;
select * from emp;
我们可以看到这张emp表记录了员工的姓名(ename)和部门编号(deptno),但是没有部门的名称;
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
14 rows in set (0.01 sec)
但我们发现,部门名称在dept表中
select * from dept;
+--------+------------+----------+
| DEPTNO | DNAME | LOC |
+--------+------------+----------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+
4 rows in set (0.00 sec)
因此,要完成案例中要求,需要在在emp中取出员工名字,在dept表中取出部门名字。
select ename, dname from emp,dept; // ename和dname要联合在一块显示,粘到一块。
这条查询语句将会产生56条记录,因为emp中每一员工信息(14)都会与dept中记录(4条)进行匹配,这将产生14 x 4 = 56条记录。
查询结果:以下查询结果手动省略。
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | ACCOUNTING |
| SMITH | RESEARCH |
| SMITH | SALES |
| SMITH | OPERATIONS |
.....................
| MILLER | ACCOUNTING |
| MILLER | RESEARCH |
| MILLER | SALES |
| MILLER | OPERATIONS |
+--------+------------+
56 rows in set (0.00 sec)
4. 表的别名
在写sql语句时,我们可以对表进行起别名,如上面sql语句,我们可以写成:
select e.ename, d.dname from emp e, dept d ;
使用别名的优势:
第一: 执行效率高; 以上sql语句为了,如果不使用别名,查询enme字段,它先会去emp找,再去dept表中找。
有时候,两张表中可能会存在字段名一样的情况。第二:可读性好;
5. 怎么避免笛卡尔积现象?
当然是加条件进行过滤。
思考:避免了笛卡尔积现象,会减少记录的匹配次数吗?
答案是:不会。 以以上查询案例为例,查询次数还是56次。只不过显示的是有效记录。
案例:找出每一个员工的部门名称,要求显示员工名和部门名;
为了避免笛卡尔乘积,我们需要判断两个部门的编号是否一致,如果一致则匹配。正确的写法为:
select e.ename, d.dname from emp e,dept d where e.deptno = d.deptno; // SQL92的老语法
+--------+------------+
| 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.01 sec)