SQL第2/n篇(持续更新中)从基础到进阶

作者: 粉红狐狸_dhf | 来源:发表于2020-06-30 15:32 被阅读0次

    进阶5 分组查询

    1、语法:
    select 分组函数,列(要求出现在group by后面)
    from 表
    where 条件
    group by 分组列表
    order by 排序列表

    2、执行过程:
    from 表 where条件 group by分组 having筛选 select查询 order by 排序

    3、要求:查询列表是分组函数或者出现在group by之后
    4、特点:
      1、分组筛选分为两类
                        数据源         位置及关键字
      分组前筛选       原始表中有      where 放在group by前面
      分组后筛选       需要先查一下    hanving  放在group by 后面
      
      ①分组函数做条件放在having中,因为分组函数是不在原始表中的
      ②都可以筛选时优先使用原始表里的where筛选
      
      2、多字段分组,逗号隔开,顺序无影响
    

    查询每个部门的平均工资

    SELECT department_id 部门,AVG(salary) 平均工资
    FROM employees
    GROUP BY department_id;
    
    分组前的查询(在表中可以找到筛选字段,如:email)

    查询邮箱中有a字母的每个部门的员工数

    SELECT COUNT(*) ,department_id 
    FROM employees
    WHERE email LIKE '%a%'
    GROUP BY department_id;
    
    分组后查询(在表中找不到要筛选的字段)

    在每个员工数>2的部门查询员工奖金

    #①每个部门的员工数
    SELECT COUNT(*),department_id
    FROM employees
    GROUP BY department_id
    #②对①的结果进行筛选,筛选员工数>2
    SELECT commission_pct,COUNT(*) AS 员工人数,department_id
    FROM employees
    GROUP BY department_id
    HAVING 员工人数>2;
    

    查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资

    SELECT job_id,MAX(salary) AS 最高工资
    FROM employees
    WHERE commission_pct IS NOT NULL
    GROUP BY job_id 
    HAVING 最高工资>12000;
    

    查询领导编号>102的每个领导手下的最低工资>5000的领导编号,及最低工资

    SELECT manager_id,MIN(salary) 最低工资
    FROM employees
    WHERE manager_id > 102
    GROUP BY manager_id
    HAVING 最低工资>5000;
    
    按表达式或者函数分组

    按员工姓名的长度分组,查询每组的员工个数,筛选员工个数>5

    SELECT COUNT(*) AS 员工个数,LENGTH(last_name) AS 姓名长度
    FROM employees
    GROUP BY 姓名长度
    HAVING 员工个数>5;
    #不同数据库where 不支持别名查询
    
    按多个字段进行分组

    查询不同工种不同部门的平均工资

    SELECT AVG(salary),job_id,department_id
    FROM employees
    GROUP BY job_id,department_id;
    #前后循序没有影响
    

    查询不同工种不同部门的平均工资,降序排列

    SELECT AVG(salary) 平均工资,job_id,department_id
    FROM employees
    GROUP BY job_id,department_id
    ORDER BY 平均工资 DESC;
    

    进阶六:连接查询

    1、分类

    按年代分类
    sql92:仅支持内连接
    sql99【推荐】:支持内连接+外连接(左外,右外)+交叉连接

    按功能分类
    (1)内连接:
    等值连接,非等值连接,自连接
    (2)外连接:
    左外连接,右外连接,全外连接
    (3) 交叉连接:

    一、sql92标准:直只支持内连接

    ①、多表等值连接的结果为多表的交集
    ②、n个表连接至少需要n-1个连接条件
    ③、多表的顺序没有要求
    ④、一般需要为表起别名,用了别名就不能再用原来的表名了
    ⑤、可以搭配前面所有的子句使用:where、group by 、(两者的后面一般不用别名)order by(可以使用别名)

    查询女神和对应的男神的名字

    SELECT NAME,boyName FROM beauty,boys
    WHERE beauty.boyfriend_id=boys.id;
    #其实他还是笛卡尔积的形式去匹配,只不过有where条件进行了筛选
    

    查询员工名和对应的部门名

    SELECT last_name,department_name FROM employees,departments
    WHERE employees.`department_id`=departments.`department_id`;
    
    为表起别名,如果用了别名,在限定时就不能再用原来的表名了

    查询员工名,工种号、工种名

    SELECT last_name,a.job_id,job_title
    FROM employees a,jobs b
    WHERE a.`job_id`=b.`job_id`;
    #当要查的字段在两个表中都存在时,要通过表名进行限定
    
    加筛选条件 where 等值连接后用 and 关键词连接

    查询城市中第二个字符为o的部门名和城市名

    SELECT department_name,city
    FROM departments d,locations l
    WHERE d.`location_id`=l.`location_id`
    AND l.`city` LIKE '_o%';
    
    加分组条件

    查询有奖金的每个部门的部门名和领导编号以及最低工资

    SELECT department_name,e.manager_id,MIN(salary)
    FROM departments d ,employees e
    WHERE d.`department_id`=e.`department_id`
    AND e.`commission_pct` IS NOT NULL
    GROUP BY department_name,e.manager_id;
    

    有了group by就要时刻关注查询的后面的字段除了聚合函数之外有没有都写上,不写在group by后面默认的是查询的字段一一对应,最好都写上,尽管分组也用不到

    ps:

    最后根据e.namage_id 和 根据 d.manager_id分组的结果是不一样的
    根据employees表的领导分,会出现Sal部门里的多个领导
    根据departments表的领导分,只会出现一个领导
    employees里有departments不存在的领导编号【好像发现了什么,哈哈】

    实现三表连接 (表的顺序无所谓)

    查询员工名、、部门名、城市

    SELECT last_name,department_name,city
    FROM departments d ,locations l,employees e 
    WHERE d.`location_id`=l.`location_id`
    AND e.`department_id`=d.`department_id`;
    
    非等值连接 (表的顺序没有关系,之后也可正常加其他子句)
    CREATE TABLE job_grades
    (grade_level VARCHAR(3),
     lowest_sal  INT,
     highest_sal INT);
    
    INSERT INTO job_grades
    VALUES ('A', 1000, 2999);
    
    INSERT INTO job_grades
    VALUES ('B', 3000, 5999);
    
    INSERT INTO job_grades
    VALUES('C', 6000, 9999);
    
    INSERT INTO job_grades
    VALUES('D', 10000, 14999);
    
    INSERT INTO job_grades
    VALUES('E', 15000, 24999);
    
    INSERT INTO job_grades
    VALUES('F', 25000, 40000);
    

    查询员工的工资和工资级别

    SELECT salary,grade_level
    FROM employees e ,job_grades j
    WHERE salary BETWEEN j.`lowest_sal` AND j.`highest_sal`;
    
    自连接

    查询员工名和他的领导的名字
    首先,这些字段都在一张表里
    其次,我根据last_name找到manager_id,然后根据manager_id去找emploee_id(emploee_id实际就是要找的manager_id)

    select e.last_name,e.employee_id,m.employee_id,m.last_name
    from employees e ,employees m
    where e.manager_id=m.`employee_id`;
    

    sql99

    1.语法:
    select 字段列表
    from 表1 别名 【连接类型】
    join 表2 别名
    on 连接条件
    【where】
    【group by】
    【order by】
    
    2.连接类型:
    内连接:inner
        等值连接
        非等值连接
        自连接
    外连接:
        左外:left 【outer】
        右外:right【outer】
        全外:full 【outer】
    交叉连接:cross
    
    一、内连接 inner join (inner可以省略)
    1、等值连接

    案例1:查询员工名、部门名

    select last_name,department_name
    from employees e
    inner join departments d on e.`department_id`=d.`department_id`;
    

    案例2:查询包含e的员工名和工种名(筛选)

    select last_name,job_title
    from jobs j
    inner join employees e
    on j.`job_id`=e.`job_id`
    where last_name like '%e%';
    

    案例3:查询每个城市部门个数>3的城市名和部门个数(分组+筛选)

    select city,count(*) 部门个数
    from locations l
    inner join departments d
    on l.`location_id`=d.`location_id`
    group by l.`city`
    having 部门个数>3;
    

    案例4:查询每个部门的员工个数>3的员工个数和部门名,并按个数降序排列

    select count(*) 员工个数,department_name
    from employees e
    inner join departments d
    on d.`department_id`=e.`department_id`
    group by d.department_name
    having count(*)>3
    order by 员工个数 desc;
    

    案例5:查询员工名、工种名、部门名,并按部门名降序(三表连接)

    select last_name,job_title,department_name
    from employees e 
    inner join jobs j on e.`job_id`=j.`job_id`
    inner join departments d on d.`department_id`=e.`department_id`
    order by department_name desc;
    
    非等值连接

    查询员工的工资级别

    select salary ,`grade_level`
    from employees e
    join `job_grades` jg
    on e.`salary` between jg.`lowest_sal` and jg.`highest_sal`;
    

    查询每个工资级别的个数>20,降序排列

    SELECT 
        #salary ,#写上salary也可以显示,但是不建议写,因为不是group by里的字段
        `grade_level`,count(*)
    FROM employees e
    JOIN `job_grades` jg
    ON e.`salary` BETWEEN jg.`lowest_sal` AND jg.`highest_sal`
    group by jg.`grade_level`
    having COUNT(*)>20
    order by count(*) desc;
    
    自连接

    查询员工的名字、领导的名字

    select e.last_name,m.last_name
    from employees e
    join employees m on e.`manager_id`=m.`employee_id`;
    

    二、外连接

    内连接干的都是些查询交集的事情,对于不是交集的事情就干不了了
    外连接查的是:在一个表中有,另一个表没有的数据,没有的数据用null填充
    怎么理解呢?就是两个表先join吧,
    此时内连接只选取两个表都有数据的部分
    外连接根据主表选数据,不管另一个表的数据是否完整
    也就是说,会存在主表的字段有值,从表的字段是null填充的情况

    特点:
    1、外连接有主从表之分,主表会全部显示。
        对于匹配不上的用null值填充
        对于匹配上的正常显示
    2、左外连接左边是主表,右外右边的是主表
    3、通过交换两个表的顺序可以实现左外和右外的转换
    4、全连接=内连接+表1有但表2没有(用null填充)+表2有表1没有(用null填充)
    

    查询男朋友不在男神表的女神的名字

    SELECT g.`name`, b.*
    FROM beauty g
    LEFT JOIN boys b ON g.`boyfriend_id`=b.`id`#看一下数据
    
    select *
    from beauty g
    left join boys b on g.`boyfriend_id`=b.`id`
    where b.`id` is null;
    

    案例:查询没有员工的部门

    #左外
    select d.department_id,department_name
    from departments d
    left join employees e
    on d.`department_id`=e.`department_id`
    where e.`department_id` is null;
    
    #右外
    SELECT d.department_id,department_name
    FROM employees e
    right JOIN departments d
    ON d.`department_id`=e.`department_id`
    WHERE e.`department_id` IS NULL;
    
    3、全连接 (不支持全连接查询)只是演示一下

    表1与表2的内连接+表1在表2中匹配不到用null填充的部分+表2在表1中匹配不到用null填充的部分

    use girls;
    select b.*,bo.*
    from beauty b
    full join boys bo
    on b.`boyfriend_id`=bo.`id`
    
    4、交叉连接 (笛卡尔乘积) 不需要on条件
    SELECT b.*,bo.*
    FROM beauty b
    cross JOIN boys bo
    

    —————————做题线——————————
    1、查询编号>3的女神的男朋友的信息,如有信息详细列出,没有信息用null填充

    select b.id,b.name ,bo.*
    from beauty b
    left join boys bo
    on b.boyfriend_id=bo.id
    where b.id>3;
    

    2、查询哪个城市没有部门

    select city 
    from locations l
    left join departments d
    on l.`location_id`=d.`location_id`
    where d.`department_id` is null;
    

    3、查询部门名为SAL 或者IT的员工的信息
    部门表为主表,为什么呢?因为有部门的不一定有员工

    select department_name,e.*
    from departments d
    left join employees e
    on e.`department_id`=d.`department_id`
    where d.`department_name` ='SAL'
    OR D.`department_name`='IT';
    

    in的用法

    select department_name,e.*
    from departments d
    left join employees e
    on e.`department_id`=d.`department_id`
    where d.`department_name` in('SAL','IT');
    

    看一下连接的各种状况

    image.png image.png
    说明一下这个beauty和boys表 beauty.png boys.png 表里的信息不一定对,仅供操作实验。
    参考出处真心讲的不错,推荐!!!这是跟课手敲的笔记,follow 我也是可以的!

    相关文章

      网友评论

        本文标题:SQL第2/n篇(持续更新中)从基础到进阶

        本文链接:https://www.haomeiwen.com/subject/pndxqktx.html