MySQL-连接查询

什么是连接查询?

  • 在实际开发中,大部分的情况下都不是从单表中查询数据,一般都是多张表联合查询取出最终的结果。
  • 在实际开发中,一般一个业务都会对应多张表,比如:学生和班级,最少两张表。

连接查询的分类

根据语法出现的年代来划分的话,包括:

  • SQL92(一些老的DBA可能还在使用这种语法。DBA:DataBase Administrator,数据库管理员)
  • SQL99(比较新的语法)

根据表的连接方式来划分,包括:
内连接:

  • 等值连接
  • 非等值连接
  • 自连接

外连接:

  • 左外连接(左连接)
  • 右外连接(右连接)
  • 全连接

笛卡尔积现象

两张表进行连接查询的时候,如果没有任何条件进行限制,最终的查询结果条数是两张表记录条数的乘积

比如,一张表a有6条记录,表b有12条记录,那么第一张表的每一行都会与第二张表的每一条记录都会进行一次匹配,最终有72条的记录,这种现象存在数据冗余,也存在无效的记录,不合理的记录

如何避免笛卡尔积现象

根据定义,我们知道,连接查询时,对连接条件进行设置可以避免这种现象

但是,匹配次数并不会减少,只是查询结果记录减少了

内连接

关键字:join on或者inner join on,老版的SQL语句on可以替换成where

inner可以省略

a表与b表内连接时,a、b两张表的地位是等同的,不分主次,不分主副表,如果两张表有不匹配的地方,例如null,则会自动忽略这条记录

等值连接

连接条件是等量关系,就是这么简单

语法:
    select
    ...
        A
    join
        B
    on
        连接条件

非等值连接

连接条件中的关系是非等量关系

语法与等值连接一样,只是on后面的连接条件不同

select 
    e.ename,e.sal,s.grade
from
    emp e
inner join
    salgrade s
on
    e.sal between s.losal and s.hisal;

自连接

最大的特点:

  • 一张表看做两张或者多张表
  • 自己连接自己
案例:找出每个员工的上级领导,要求显示员工名和对应的领导名。
mysql> select empno,ename,mgr from emp;
emp a 员工表
+-------+--------+------+
| empno | ename  | mgr  |
+-------+--------+------+
|  7369 | SMITH  | 7902 |
|  7499 | ALLEN  | 7698 |
|  7521 | WARD   | 7698 |
|  7566 | JONES  | 7839 |
|  7654 | MARTIN | 7698 |
|  7698 | BLAKE  | 7839 |
|  7782 | CLARK  | 7839 |
|  7788 | SCOTT  | 7566 |
|  7839 | KING   | NULL |
|  7844 | TURNER | 7698 |
|  7876 | ADAMS  | 7788 |
|  7900 | JAMES  | 7698 |
|  7902 | FORD   | 7566 |
|  7934 | MILLER | 7782 |
+-------+--------+------+
emp b 领导表
+-------+--------+
| empno | ename  |
+-------+--------+
|  7566 | JONES  |
|  7698 | BLAKE  |
|  7782 | CLARK  |
|  7788 | SCOTT  |
|  7839 | KING   |
|  7902 | FORD   |
+-------+--------+

员工的领导编号 = 领导的员工编号

select 
    a.ename as '员工名',b.ename as '领导名'
from
    emp a
inner join
    emp b
on
    a.mgr = b.empno;

+--------+--------+
| 员工名 | 领导名 |
+--------+--------+
| SMITH  | FORD   |
| ALLEN  | BLAKE  |
| WARD   | BLAKE  |
| JONES  | KING   |
| MARTIN | BLAKE  |
| BLAKE  | KING   |
| CLARK  | KING   |
| SCOTT  | JONES  |
| TURNER | BLAKE  |
| ADAMS  | SCOTT  |
| JAMES  | BLAKE  |
| FORD   | JONES  |
| MILLER | CLARK  |
+--------+--------+

外连接

外连接与内连接的区别

内连接:

  • 假设A和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接。
  • AB两张表没有主副之分,两张表是平等的。

外连接:

  • 假设A和B表进行连接,使用外连接的话,AB两张表中有一张表是主表,一张表是副表,主要查询主表中的数据,捎带着查询副表,当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配

外连接的分类?
左外连接(左连接):表示左边的这张表是主表。
右外连接(右连接):表示右边的这张表是主表。

左连接有右连接的写法,右连接也会有对应的左连接的写法,是相对的

外连接最重要的特点是:主表的数据无条件的全部查询出来

// outer可以省略。
select 
    a.ename '员工', b.ename '领导'
from
    emp b
right outer join
    emp a
on
    a.mgr = b.empno;

+--------+-------+
| 员工   | 领导  |
+--------+-------+
| SMITH  | FORD  |
| ALLEN  | BLAKE |
| WARD   | BLAKE |
| JONES  | KING  |
| MARTIN | BLAKE |
| BLAKE  | KING  |
| CLARK  | KING  |
| SCOTT  | JONES |
| KING   | NULL  |
| TURNER | BLAKE |
| ADAMS  | SCOTT |
| JAMES  | BLAKE |
| FORD   | JONES |
| MILLER | CLARK |
+--------+-------+

多张表连接

案例:找出每一个员工的部门名称以及工资等级

EMP e
+-------+--------+---------+--------+
| empno | ename  | sal     | deptno |
+-------+--------+---------+--------+
|  7369 | SMITH  |  800.00 |     20 |
|  7499 | ALLEN  | 1600.00 |     30 |
|  7521 | WARD   | 1250.00 |     30 |
|  7566 | JONES  | 2975.00 |     20 |
|  7654 | MARTIN | 1250.00 |     30 |
|  7698 | BLAKE  | 2850.00 |     30 |
|  7782 | CLARK  | 2450.00 |     10 |
|  7788 | SCOTT  | 3000.00 |     20 |
|  7839 | KING   | 5000.00 |     10 |
|  7844 | TURNER | 1500.00 |     30 |
|  7876 | ADAMS  | 1100.00 |     20 |
|  7900 | JAMES  |  950.00 |     30 |
|  7902 | FORD   | 3000.00 |     20 |
|  7934 | MILLER | 1300.00 |     10 |
+-------+--------+---------+--------+
DEPT d
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+
SALGRADE s
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+

注意,解释一下:
    ....
        A
    join
        B
    join
        C
    on
        ...
    
    表示:A表和B表先进行表连接,连接之后A表继续和C表进行连接。

    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 s.losal and s.hisal;
    
    +--------+------------+-------+
    | ename  | dname      | grade |
    +--------+------------+-------+
    | SMITH  | RESEARCH   |     1 |
    | ALLEN  | SALES      |     3 |
    | WARD   | SALES      |     2 |
    | JONES  | RESEARCH   |     4 |
    | MARTIN | SALES      |     2 |
    | BLAKE  | SALES      |     4 |
    | CLARK  | ACCOUNTING |     4 |
    | SCOTT  | RESEARCH   |     4 |
    | KING   | ACCOUNTING |     5 |
    | TURNER | SALES      |     3 |
    | ADAMS  | RESEARCH   |     1 |
    | JAMES  | SALES      |     1 |
    | FORD   | RESEARCH   |     4 |
    | MILLER | ACCOUNTING |     2 |
    +--------+------------+-------+

子查询

什么是子查询?子查询都可以出现在哪里?

select语句当中嵌套select语句,被嵌套的select语句是子查询

  1. 子查询可以出现的位置
select
    ..(select).
from
    ..(select).
where
    ..(select).
  1. where子句中可以使用子查询

Union

union比较鸡肋,但也有奇效,可以将查询结果集相加

案例:找出工作岗位是SALESMAN和MANAGER的员工?

第一种:select ename,job from emp where job = 'MANAGER' or job = 'SALESMAN';
第二种:select ename,job from emp where job in('MANAGER','SALESMAN');
+--------+----------+
| ename  | job      |
+--------+----------+
| ALLEN  | SALESMAN |
| WARD   | SALESMAN |
| JONES  | MANAGER  |
| MARTIN | SALESMAN |
| BLAKE  | MANAGER  |
| CLARK  | MANAGER  |
| TURNER | SALESMAN |
+--------+----------+
第三种:union
select ename,job from emp where job = 'MANAGER'
union
select ename,job from emp where job = 'SALESMAN';
+--------+----------+
| ename  | job      |
+--------+----------+
| JONES  | MANAGER  |
| BLAKE  | MANAGER  |
| CLARK  | MANAGER  |
| ALLEN  | SALESMAN |
| WARD   | SALESMAN |
| MARTIN | SALESMAN |
| TURNER | SALESMAN |
+--------+----------+

两张不相干的表中的数据拼接在一起显示时,会排成一列

select ename from emp
union
select dname from dept;

+------------+
| ename      |
+------------+
| SMITH      |
| ALLEN      |
| WARD       |
| JONES      |
| MARTIN     |
| BLAKE      |
| CLARK      |
| SCOTT      |
| KING       |
| TURNER     |
| ADAMS      |
| JAMES      |
| FORD       |
| MILLER     |
| ACCOUNTING |
| RESEARCH   |
| SALES      |
| OPERATIONS |
+------------+

拼接的数据必须两两相对应。不能一张表是一个数据,另一张表是两个数据,这样无法拼接!

mysql> select ename,sal from emp
    -> union
    -> select dname from dept;  
ERROR 1222 (21000): The used SELECT statements have a different number of columns


limit

  1. limit是mysql特有的,其他数据库中没有,不通用。(Oracle中有一个相同的机制,叫做rownum)
  2. limit取结果集中的部分数据,这是它的作用

语法机制

limit startIndex, length

  • startIndex表示起始位置,从0开始,0表示第一条数据。
  • length表示取几个,取的记录的条数

limitselect语句最后执行的一个环节

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容