MySQL笔记3

连接查询
1、什么是连接查询?
    从一张表中单独查询称为“单表查询”。
    emp表和dept表联合起来查询数据,从emp表中获取员工的名字,从dept表中获取部门的名字。
    这种跨表查询,多张表联合起来查询数据,被称为连接查询。
2、连接查询的分类:
    根据语法的年代分类:
        SQL92:1992年出现的语法
        SQL99:1999年出现的语法
        我们这重点学习SQL99
    根据表连接的方式分类:
        内连接:
            等值连接
            非等值连接
            自连接
        外连接:
            左外连接(左连接)
            右外连接(右链接)
        全连接
2.1多个表连接查询的时候,我们只在select 后面直接写一个“*”,代表所有表的所有字段,全查出来。
    如果加上“表名.*”,只是代表这张表的“所有字段”。
3、当两种表进行连接查询时,没有任何条件的限制会发生什么现象?
    select ename,dname from emp,dept; [发现查询结果右56条记录]
    emp表中有14条记录,dept表中有4条记录。
    没有任何条件的情况下会发现:
    最终的查询结果集会用emp表中的第一条记录与dept表中的每一条记录进行匹配,最终dept表中有多少条记录就会生成多少条新的记录
    最终的查询结果集会用emp表中的第二条记录与dept表中的每一条记录进行匹配,最终dept表中有多少条记录就会生成多少条新的记录
    ... 
    以此类推,查询结果集最终生成的记录条数 = emp的记录条数 * dept的记录条数
    最终的查询结果集会用emp表中的每一条记录与dept表中的每一条记录进行匹配,生成一条新的记录
    三张表也是一样的道理:以此类推。
4、两种表进行连接查询的时候,没有任何条件限制的时候,最终的查询结果条数,是两种表条数的乘积,
   这种现象被称为:笛卡尔积现象。(笛卡尔发现的,这是一个数学现象。)
5、怎样避免笛卡尔积现象?
    连接时加条件,满足这个条件的记录被筛选出来。
    示例:查询某个员工始于哪个部门的?
    select ename,dname from emp,dept where emp.deptno=dept.deptno;
    emp.deptno:员工表的部门编号
    dept.deptno:部门表的部门编号
    查询结果是使用某条员工的记录去匹配所有部门的记录。
    不管该员工是不是这个部门的,该员工的信息都要与这个部门的这条记录组成一条新的记录。
    如果该员工不是某个部门的,组成的这条记录是没有意义的,所以要加条件“emp.deptno=dept,deptno”。
    当员工表的部门编号和部门表的部门编号相同时,说明员工就是这个部门的,此时这条记录才有意义,才保留此条记录。
6、只要有表的连接肯定会有“笛卡尔积”。通过where加了条件限制之后,虽然查询出来的记录数减少了,
    但是最终匹配的次数是不会减少的,只是匹配出来的结果集被筛选条件过滤了。
    如果通过on加的条件就会在形成临时表之前使用过滤条件,避免了生成一笛卡尔积临时表,提高了效率。
    例如:select ename from emp,dept;
    虽然没有用到dept表中的字段,但是只要写到“... from emp,dept”的表都会连接形成笛卡尔积。
7、    select ename,dname from emp,dept where emp.deptno=dept.deptno;【效率低,因为ename,和dname没有指定是在哪个表中的字段,MySQL需要去两种表或者多张表中找】
    select emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno;【效率高】
8、select emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno;
    表也可以起别名:
   select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno;【as可以省略】
   字段起了别名之后:可以使用原名也可以使用别名。
   但是表起了别名之后就只能使用别名了,原名就失效了。
   mysql> select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno;
    +--------+------------+
    | ename  | dname      |
    +--------+------------+
    这种语法查询之后字段名就只是,ename、dname了前面的e和d都省略了。
9、降低连接的次数
    通过笛卡尔积现象,得出表的连接次数越多效率越低,尽量减少表的连接次数。【可以使用on加条件,在形成临时表的时候使用的条件】

内连接之等值连接
案例:查询每个员工坐在的部门名称,显示员工名和部门名。
    【SQL92语法】
    select 
        e.ename,d.dname 
    from 
        emp e,dept d 
    where 
        e.deptno=d.deptno;【因为条件是等值关系所以被称为“等值连接”】
    【SQL99语法】:把92语法中多个表之间的逗号换成了join...,
                  把92语法中的where换成了on
    select
        e.ename,d.dname 
    from 
        emp e
    inner join 【inner 可以省略不写,默认就是内(inner)连接,可以写多个join】
        dept d 
    on 
        e.deptno=d.deptno;【可以只写inner join,省略后面的连接条件,不过这样做没有意义】
    
    在92语法中,表连接的条件和后期连接完过滤的条件,糅杂在一起,都写在where语句中。【结构不清晰】
    在99语法中,表连接的条件和后期连接完过滤的条件分离,表连接的条件写在on后面,连接完后过滤的条件写在where之后。【结构清晰】
10、还可以表连接的时候使用join,但是写连接条件的时候使用where。
    还可以在一条SQL中表连接同时使用join和逗号“,”
    表连接的过程中只要有逗号的存在那么连接条件必须得写在where后面,
    所有的表连接都使用join的时候,表的连接条件才可以写在on中。

内连接之非等值连接
示例:找出每个员工的薪资等级,要求显示员工名、薪资、工作位置、薪资等级:
        select 
            ename,loc,sal,grade 
        from 
            emp 
        join         【省略默认是inner内连接】
            dept 
        join         【省略默认是inner内连接】
            salgrade 
        on 
            emp.deptno=dept.deptno 
        and 
            (sal between losal and hisal);【条件不是一个等量关系称为非等值连接】            

内连接之自连接
1、查询员工的上级领导,要求显示员工名和对应的领导名?
   select e1.ename,e2.ename from emp e1 join emp e2 on e1.mgr=e2.empno;
   e1表:左边的是员工表的信息,e1.ename是员工的姓名
   e2表:右边是领导表的信息,e2.name是员工的领导的姓名
   连接之后形成了笛卡尔积,通过“员工的领导的编号”=“当领导的员工的编号”过滤【员工的领导编号=领导的员工编号】
    【自连接必须定义表的别名,因为多张表连接查询的时候,表名必须唯一,
    表一旦定义了别名就只能使用别名访问表中的字段了,所以就形成了唯一的表名】
2、自连接的技巧,一张表看成两张或多张表。
    
外连接
1、示例:查询员工的姓名和员工的所属部门,如果这个部门没有员工就显示null。
    select 
        ename,dname 
    from 
        emp  
    right outer join   【这里的outer可以省略不写,但是rigth或者left不能省略】
        dept 
    on 
        emp.deptno=dept.deptno;
        
2、直接写join等价于inner join  【内连接】
   直接写left join 等价于 left outer join 【左外连接】
   直接写right join 等价于 right outer join 【右外连接】
3、inner join可以单独书写,不带连接条件on。【默认就是连接成一个笛卡尔积】
   outer join(左、右)不能单独书写,不带连接条件on是错误的。
4、同一条SQL语句中可以即存在内连接又存在外连接。
5、内连接两种表是平等的关系:
        能匹配上就显示,不能匹配上就不显示。
   外连接表之间产生了主次关系:
        左连接左边的是主表,右边的是副表。
        右连接右边的是主表,左边的是副表。
   主表中的数据会全部显示出来,能满足某个条件的话,关联着把副表的记录也查出来。
6、使用副表中的第一条记录匹配主表中的所有记录,符合规则就查出来
   使用副表中的第二条记录匹配主表中的所有记录,符合规则就查出来
   ....以此类推,查询结果集中副表中的记录是按规则排列的。
   如果副表中的记录都已经遍历比较完了,之后主表中还有未显示的记录
   那么主表的记录显示出来,与之同一条记录的副表中的该字段处显示“null”。
   【这是MySQL5.7的规则】
   使用主表中的第一条记录,与副表中的每一条记录,符合规则的就查出来
   使用主表中的第二条记录,与副表中的每一条记录,符合规则的就查出来
   ...以此类推,查询结果集中主表的记录是按照规怎排列的。
   如果在遍历的过程中副表中没有与主表中该记录对应的行,
   那么主表本行单独生成一行记录,副表的位置自动填充null
   主表遍历比较完了,主表的记录也就全部显示了。
   【这是MySQL5.5的规则】
7、任何一个右连接都有左连接的写法。
   任何一个左连接都有右连接的写法。
8、示例:查询每个员工的上级领导,要求显示所有员工的名字和领导名?
    select e1.ename,e2.ename from emp e1 left join emp e2 on e1.mgr=e2.empno;
9、示例:找出每个员工的部门名称以及工资等级,
    要求显示员工名、部门名、薪资、薪资等级?
    第一种方式:
        select     
            dname,ename,sal,grade
        from 
            emp 
        left join 
            dept 
        on 
            emp.deptno=dept.deptno
        left join 
            salgrade 
        on 
            (sal between losal and hisal);
        【语法结构】
        select
            ...
        from 
            ...
        letf join
            ...
        on
            ....
        letf join
            ...
        on
            ....
    第二种方式:
        select 
            ename,dname,sal,grade
        from 
            emp 
        join 
            dept 
        join 
            salgrade
        on 
            emp.deptno=dept.deptno 
        and 
            (sal between losal and hisal);
            
        【语法结构】
        select
            ...
        from 
            ...
        join
            ...
        join
            ...
        on
            ...
        and
            ...
10、示例:找出每个员工的部门名称以及工资等级,还有上级领导。
    要求显示员工名、领导名、部门名、薪资、薪资等级。
    select
        e1.ename,e2.ename,dname,e1.sal,grade
    from
        emp e1 
    left join 
        emp e2
    on
        e1.mgr=e2.empno
    left join 
        dept 
    on 
        e1.deptno=dept.deptno
    left join 
        salgrade 
    on 
        e1.sal between losal and hisal;
        
    【或者,内连接和外连接组合使用】
    select
        e1.ename '员工名',e2.ename '领导名',dname,e1.sal,grade
    from
        emp e1 
    left join    【在这里仅仅保留左边表中全部的数据】
        emp e2
    on
        e1.mgr=e2.empno
    join 
        dept 
    on 
        e1.deptno=dept.deptno
    join 
        salgrade 
    on 
        e1.sal between losal and hisal;
11、示例:每个领导下面各管理了多少个员工?没有管理员工的员工也显示出来。
    e1是员工表
    e2是领导表
    select 
        e1.ename,case ifnull(e2.ename,0) when '0' then '0' else count(*) end '管理的员工数量'
    from 
        emp e1 
    left join 
        emp e2
    on 
        e1.empno=e2.mgr
    group by
        e1.ename;
        
子查询
1、什么是子查询?
    select语句中嵌套select语句,被嵌套的select语句被称为子查询。
2、子查询都可以出现在哪里?
    select
        ...(select). 【可以出现在select语句后面,这里出现的子查询一次只能返回一条语句,多于一条就报错】
    from 
        ...(select). 【可以出现在from语句后】
    where
        ...(select). 【可以出现在where语句后,in里面】
3、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);
            这条语句的执行顺序:先执行“(select min(sal) from emp)”在执行外层的查询
4、from子句中的子查询
    注意:from后面的子查询,可以将子查询的查询结果当作一张临时表。(技巧)
    案例:找出每个岗位的平均工资的薪资等级。
    select 
        t.*,s.grade
    from
        (select job,avg(sal) as avgsal from emp group by job) t【avg(sal)需要起一个别名,因为后续使用该字段的时候不能“t.avg(sal)”,才可以在后续的连接条件用,整个表起的别名叫做t,方便后续使用】
    join
        salgrade s
    on
        t.avgsal between s.losal and s.hisal;  【其中的“t.avgsal”可以省略t,直接写“avgsal”】

union
1、union用于合并查询结果集。
2、案例:查询工作岗位是manager或者salesman的员工:
    方式一:mysql> select ename,job from emp where job='manager' or job='salesman';
            mysql> select ename,job from emp where job in('manager','salesman');
    方式二:使用union方式合并查询结果集:
        select ename,job from emp where job = 'manager'
        union 
        select ename,job from emp where job='salesman';
    使用union的效率高一些。对于表连接来说,每连接一次新表,
    则匹配的此时满足笛卡尔积,成倍翻...
    union可以减少匹配的次数,减少匹配次数的情况下还能完成两个结果集的拼接。
3、注意:union在进行结果集的拼接的时候要求两个结果集的列数相同。
    //以下的SQL语句是错误的
    select ename,job from emp where job = 'manager'
    union 
    select ename from emp where job='salesman';
4、注意:union在进行结果集的拼接的时候上下只要列数相同就可以,
    字段名,甚至类型都可以不同,mysql都可以帮助我们拼接到一起。
    【拼接之后结果集的列名是 ename,job 以上面的为准】
    select ename,job from emp where job = 'manager'
    union 
    select ename,sal from emp where job='salesman';
    
limit
1、limit作用:将查询结果集的一部分取出来,通常使用在分页查询当中    
2、limit使用的语法格式:limit startIndex, length 【从第startIndex条开始输出length条记录,第一条记录的下标是0】
    案例:按照降序排序,去除排名在前5名的员工?
      mysql> select * from emp order by sal desc limit 5;【省略startIndex,默认startIndex就是0】
      mysql> select * from emp order by sal desc limit 0, 5;【如果到末尾也凑不够5条,那么凑了几条就输出几条】
3、注意:在MySQL中limit在order by之后执行。
通用分页公式:limit (pageNo-1)*pageSize,pageSize

SQL大总结
1、
select
    ...
from
    ...
where
    ...
group by
    ...
having
    ...
order by
    ...
limit
    ...
执行顺序:
    from
    where
    group by
    having
    select
    order by
    limit

    

【重点:条件子句】 
on、where、having三个都可以加条件子句中:
1.on最先执行,where次之、having最后执行。
2.因为on是先把不符合条件的记录过滤后才进行统计,它可以减少中间运算要处理的数据(但是匹配的次数一次都没有少),按理说应该速度最快。
3.on语句的执行实在join语句之前的,也就是说两张表数据行之间进行匹配的时候,会先判断数据行是否符合on语句后面的条件,再决定是否join。
4.先执行on,后执行where,on是关联关系,where是对关联关系的筛选。

具体什么时候使用内连接什么时候使用外连接呢?只需要由外键区分即可:
如果外键不能为空,优先使用内连接;
如果外键可以为空:
假如只需要查询那些在另一张表中有相对应的记录,使用内连接;
假如需要查询左(右)侧表中所有符合条件的记录,使用左(右)外连接;


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛英豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值