• 学习MySQL-第五章


    目录

    21,去除重复记录

    22,连接查询

    22.1什么是连接查询

    22.2连接查询的分类

    22.3当两张表进行连接查询时,没有任何条件的限制会发生什么现象?

    22.4怎么避免笛卡尔积现象?

    22.5内连接之等值连接

    22.6内连接之非等值连接

    22.7内连接之自连接

    22.8外连接

    22.9三张表,四张表怎么连接?

     23,子查询

    23.1什么是子查询

    23.2子查询都可以出现在哪里

    23.3where子句中的子查询

    23.4from子句中的子查询

    23.5select后面出现的子查询(这个内容不需要掌握,了解即可!)

    24,union合并查询结果集


    21,去除重复记录

    注意:原表数据不会被修改,只是查询结果去重

    去重需要使用一个关键字:distinct

    mysql> select distinct job from emp;

    +-------------------+

    | job                  |

    +-------------------+

    | CLERK            |

    | SALESMAN    |

    | MANAGER     |

    | ANALYST        |

    | PRESIDENT   |

    +--------------------+

    mysql> select ename,distinct job from emp;

    这样写是错误的,语法错误

    distinct只能出现在所有字段的最前方

    //distinct出现在job,deptno两个字段之前,表示两个字段联合起来去重

    mysql> select distinct job,deptno from emp;

    +---------------------+-----------+

    | job                    | deptno   |

    +--------------------+------------+

    | CLERK           |     20       |

    | SALESMAN    |     30       |

    | MANAGER     |     20       |

    | MANAGER     |     30       |

    | MANAGER     |     10       |

    | ANALYST       |     20       |

    | PRESIDENT  |     10       |

    | CLERK           |     30      |

    | CLERK           |     10       |

    +-------------------+------------+

    例:统计一下工作岗位的数量

    mysql> select count(distinct job) from emp;

    +---------------------------------+

    | count(distinct job)             |

    +---------------------------------+

    |                   5                    |

    +---------------------------------+

    distinct只能出现在所有字段的前方,但是可以用分组函数

    22,连接查询

    22.1什么是连接查询

    从一张表中单独查询,称为单表查询

    emp表和dept表联合起来查询数据,从emp表中取员工名字,从detp表中取部 门名字

    这种跨表查询,多张表联合起来查询数据,被称为连接查询

    22.2连接查询的分类

    根据语法的年代分类

    SQL92:1992年的时候出现的语法

    SQL99:1999年的时候出现的语法

    这里重点学习SQL99,这个过程简单演示一下SQL92的例子

    根据表连接的方式分类

    • 内连接
    • 等值连接
    • 非等值连接
    • 自连接
    • 外连接
    • 左外连接(左连接)
    • 右外连接(右连接)
    • 全连接(不讲)

    22.3当两张表进行连接查询时,没有任何条件的限制会发生什么现象?

    例:查询每个员工所在部门名称?

     

    mysql> select ename,dname from emp,dept;

    这样会有14*4=56条记录

    注意:

    当两张表进行连接查询,没有任何条件限制的时候,最终查询结果条数,是两张表条数的乘积,这种现象被称为:笛卡尔现象。(笛卡尔发现的,这是一个数学现象。)

    22.4怎么避免笛卡尔积现象?

    连接时加条件,满足这个条件的记录被筛选出来!

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

     

    上面的查询还是比较费时的,还有更简洁的做法,就是在select的字段前面加上表明限定,另外结合起别名就可以提高效率

    //表起别名,很重要

    mysql> select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno;//SQL92 语法

     

     思考:最终查询的结果条数是14条,但是匹配的过程中,匹配的次数减少了吗?

    没有,还是56次,只不过进行了四选一,次数没有减少

    注意:通过笛卡尔积现象得出,表的连接次数越多效率越低,尽量避免表连接的次数

    22.5内连接之等值连接

    例:查询每个员工所在的部门名称,显示员工名和部门名?

    emp e和dept d表进行连接。条件是:e.deptno=d.deptno

    SQL92语法:

    select

            e.ename,d.dname

    from

            emp e,dept d

    where

            e.deptno=d.deptno;

    SQL92的缺点:

    结构不清晰,表的连接条件和后期进一步筛选的条件,都放到了where 后面

    SQL99语法:

    select

            e.ename,d.dname

    from

            emp e

    (inner) join

            dept d

    on

            e.deptno=d.deptno;

    注:inner可以省略,带着inner可读性更好,一眼就能看出是内连接

    SQL99的优点:

    表连接的条件是独立的,连接之后,如果还需要进一步筛选,再往后继续 添加where

    SQL99语法:

    select

            ...

    from

            a

    join

            b

    on

            a和b连接条件

    where

            筛选条件

    22.6内连接之非等值连接

    例:找出每个员工的薪资等级,要求显示员工名,薪资,薪资等级?

    select

            e.ename,e.sal,s.grade

    from

            emp e

    join

            salgrade s

    on

            e.sal between s.losal and s.hisal;//条件不是一个等量关系,称为非等值连接

    22.7内连接之自连接

    例:查询员工的上级领导,要求显示员工名和对应的领导名

    mysql> select empno,ename,mgr from emp;

    技巧:一张表看成两张表

    mysql> select a.ename as '员工名',b.ename as '领导名' from emp a join emp b on a.mgr=b.empno;//员工的领导编号=领导的员工编号

     以上就是内连接中的自连接,技巧:一张表看成两张表

    22.8外连接

    例:查询员工的名称与对应的岗位

    内连接(A和B连接,AB两张表没有主次关系,平等的):

    mysql> select e.ename,d.dname from emp e join dept d on e.deptno=d.deptno;

     内连接的特点:完成能够匹配上这个条件的数据查询出来

    内连接是通过deptno把emp表和dept表连接起来,查询dept表和emp表deptno 相同的记录,但是如果要把dept表和emp表中的deptno不匹配的也找出来就要 用到外连接了

    外连接(右外连接):

    mysql> select e.ename,d.dname from emp e right join dept d on e.deptno=d.deptno;//在join前面加上right

    外连接(左外连接)

    mysql> select e.ename,d.dname from dept d left join emp e on e.deptno=d.deptno;//join前面加上left

    带有right的是右外连接,又叫右连接

    带有left的是左外连接,又叫左连接

    任何一个右连接都有左连接的写法

    任何一个左连接都有右连接的写法

    right代表什么:表示将join关键字右边的这张表看成主表,主要是为了将这张表 的数据全部查询出来,捎带着关联查询左边的表

    left代表什么:和right一样,表示将join左边的表看成主表

    在外连接中,两张表连接产生了主次关系

    join前面也可以加上outer,outer是可以省略的,上面就省略了,带着可读性强, 表示是外连接

    注意:外连接的查询结果条数一定是>=内连接的查询结果条数

    例:查询每个员工的上级领导,要求显示所有员工的名字和领导名

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

    22.9三张表,四张表怎么连接?

    语法:

    select

            ...

    from

            a

    join

            b

    on

            a和b的连接条件

    join

            c

    on

            a和c的连接条件

    right join

            d

    on

            a和d的连接条件

    一条SQL中内连接和外连接可以混合,都可以出现!

    例:找出每个员工的部门名称以及工资等级,要求显示员工名,部门名,薪资,薪资等级

    mysql> select e.ename,e.sal,d.deptno,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;

     例:找出每个员工的部门名称以及工资等级,还有上级领导,要求显示员工名,领 导名,部门名,薪资,薪资等级

    mysql> select e.ename,e.sal,d.deptno,s.grade,l.ename as '上级领导' from emp e join dept d on e.deptno=d.deptno join salgrade s on e.sal between s.losal and s.hisal left join emp l on e.mgr=l.empno;

     23,子查询

    23.1什么是子查询

    select语句中嵌套select语句,被嵌套的select语句被称为子查询

    23.2子查询都可以出现在哪里

    select

            ...(select).

    from

            ...(select).

    where

            ...(select).

    23.3where子句中的子查询

    例:找出比最低工资高的员工姓名和工资?

    mysql> select ename,sal from emp where sal>min(sal);

    这样写不行,因为where子句中不能直接使用分组函数

    实现思路:

    第一步:查询最低工资是多少

    mysql> select min(sal) from emp;

    +---------------+

    | min(sal)     |

    +--------------+

    |   800.00      |

    +---------------+

    第二步:找出>800的

    mysql> select ename,sal from emp where sal>800;

    第三步:合并

    mysql> select ename,sal from emp where sal>(select min(sal) from emp);

    23.4from子句中的子查询

    注意:from后面的子查询,可以将子查询的查询结果当做一张临时表(技巧)

    例:找出每个岗位的平均工资的薪资等级

    第一步:找出每个岗位的平均工资(按照岗位分组求平均值)

    mysql> select avg(sal),job from emp group by job;

    +-------------------+-------------------+

    | avg(sal)          | job                  |

    +-------------------+-------------------+

    | 1037.500000 | CLERK            |

    | 1400.000000 | SALESMAN    |

    | 2758.333333 | MANAGER     |

    | 3000.000000 | ANALYST        |

    | 5000.000000 | PRESIDENT   |

    +-------------------+-------------------+

                     t表

    第二步:把以上的查询结果就当做一张真实存在的表t

    mysql> select * from salgrade;//s表

    +-----------+---------+------------+

    | GRADE | LOSAL | HISAL  |

    +-----------+---------+-----------+

    |     1        |   700  |  1200    |

    |     2        |  1201 |  1400    |

    |     3        |  1401 |  2000    |

    |     4        |  2001 |  3000    | 

    |     5        |  3001 |  9999    |

    +-----------+---------+----------+

    t表和s表进行表连接,条件:t表avg(sal) between s.losal and s.hisal;

    mysql> select t.*,s.grade from (select avg(sal) as avgsal,job from emp group by job) as t join salgrade s on t.avgsal between s.losal and s.hisal;

    23.5select后面出现的子查询(这个内容不需要掌握,了解即可!)

    例:找出每个员工的部门名称,要求显示员工名,部门名?

    mysql> select e.ename,(select d.dname from dept d where e.deptno=d.deptno) as dname from emp e;

    //报错:ERROR 1242 (21000): Subquery returns more than 1 row

    mysql> select e.ename,e.deptno,(select dname from dept) as dname from emp e;

    注意:对于select后面的子查询来说,这个子查询只能一次返回1条结果,多于1 条,就报错了!

    24,union合并查询结果集

    例:查询工作岗位是MANAGER和SALESMAN的员工

    mysql> select ename,job from emp where job='MANAGER' or job='SALESMAN';

    下面用union实现

    mysql> select ename,job from emp where job='MANAGER' union select ename,job from emp where job='SALESMAN';

     

     union的效率要高一些。对于表连接来说,每连接一次新表,则匹配的次数满足笛卡尔 积,成倍的翻。。。

    但是union可以减少匹配的次数,在减少匹配次数的情况下,还可以完成两个结果集的拼接

    a连接b连接c

    a 10条记录

    b 10记录

    c 10条记录

    匹配次数:1000

    a连接b一个结果:10*10 -->100次

    a连接c一个结果:10*10 -->100次

    使用union的话是:100次+100次=200次(union把乘法变成了加法运算)

    union在使用的时候有注意事项吗?

    //错误的:union在进行结果集合并的时候,要求两个结果集的列数相同

    1. select ename,job from emp where job='MANAGER'
    2. union
    3. select ename from emp where job='SALESMAN';

    //mysql可以,oracle语法严格,不可以,报错。

    //要求:结果集合并时列和列的数据类型也要一致

    1. select ename,job from emp where job='MANAGER'
    2. union
    3. select ename,sal from emp where job='SALESMAN';
  • 相关阅读:
    Kettle需求场景复现
    MyBatis的各种查询功能(5种)
    LeetCode·435.无重叠区间·贪心
    Oracle11gr2 + plsql 配置
    [附源码]计算机毕业设计JAVA车辆违章信息管理系统
    机器学习入门四
    如何通过提升客户体验带来更大的增长、更好的客户留存率?
    Java自定义注解解析
    android studio cmake生成.a文件(静态库)及调用(c c++)静态库.a
    【图像处理笔记】图像分割之形态学分水岭
  • 原文地址:https://blog.csdn.net/qq_52905520/article/details/126841692