• SQL:from、where、group by、having、order by的书写与执行顺序


    1、SQL的书写顺序与执行顺序

    • 查询中用到的关键词主要包含六个,并且他们的书写顺序依次为: select>from>where>group by>having>order by,其中select和from是必须的,其他关键词是可选的
    • 这六个关键词的执行顺序与sql语句的书写顺序并不是一样的,而是按照下面的顺序来执行:from>where>group by>having>select>order by
      • from:需要从哪个数据表检索数据
      • where:过滤表中数据的条件
      • group by:如何将上面过滤出的数据分组
      • having:对上面已经分组的数据进行过滤的条件
      • select:查看结果集中的哪个列,或列的计算结果
      • order by:按照什么样的顺序来查看返回的数据

      当一个查询语句同时出现了where,group by,having,order by的时候,执行顺序和编写顺序是:

      • 1.执行where xx对全表数据做筛选,返回第1个结果集。
      • 2.针对第1个结果集使用group by分组,返回第2个结果集。
      • 3.针对第2个结集执行having xx进行筛选,返回第3个结果集。
      • 4.针对第3个结果集中的每1组数据执行select xx,有几组就执行几次,返回第4个结果集。
      • 5.针对第4个结果集排序。

    数据库SQL语句中 where,group by,having,order by的执行顺序

    2、from与where

    2.1 from

    • from后面的表关联,是自右向左解析的
      • from后面需要接多个表,尽量把数据量小的表放在最右边来进行关联(用小表去匹配大表)

        在这里插入图片描述

    2.2 where

    • where条件的解析顺序是自下而上的
      • 把能筛选出小量数据的条件放在where语句的最左边 (用小表去匹配大表)

        在这里插入图片描述

    3、group by

    3.1 聚合函数

    3.1.1 非聚合字段必须出现在GROUP BY子句中或在聚合函数中使用

    更加详细的解释: 可以这样去理解group by和聚合函数


    在使用group by的时候,select位置处一般会有聚合语句(例如sum),一些没有聚合的字段必须要加到group by 后边。比如,select a,sum(b) from A group by a //后边必须要有a,否则报错

    关于sql:必须出现在GROUP BY子句中或在聚合函数中使用

    3.2.2 常用聚合函数

    • count() 计数
    • sum() 求和
    • avg() 平均数
    • max() 最大值
    • min() 最小值

    3.2.3 SQL中只要用到聚合函数就一定要用到group by 吗?(不一定)

    • 当只做聚集函数查询时候,就不需要进行分组了

      SELECT SUM(TABLE.A ) FROM TABLE

      上述SQL不需要使用Group by 进行分组,因为其中没有非聚合字段,所以不用Group by 也可以。

    • 聚集函数(sum(B))和非聚集字段(A)出一起出现时,需要将非聚集字段(A)进行group by,分组之后你可以计数(COUNT),求和(SUM),求平均数(AVG)等。

      SELECT TABLE.A , MAX(TABLE.B) FROM TABLE GROUP BY TABLE.A

      由于B是非聚合字段,则需要使用MAX()或者其他聚合函数进行处理

    3.2.4 Group by 与 Distinct 的区别

    原先代码
    自己修改后的代码

     CREATE TABLE IF NOT EXISTS `test_users` ( 
    `email_id` int(11) unsigned NOT NULL auto_increment, 
    `email` char(100) NOT NULL, 
    `passwords` char(64) NOT NULL, 
    PRIMARY KEY (`email_id`) 
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ; 
    
    INSERT INTO `test_users` (`email_id`, `email`, `passwords`) VALUES 
    (1, 'jims@gmail.com', '1e48c4420b7073bc11916c6c1de226bb'), 
    (2, 'jims@yahoo.com.cn', '5294cef9f1bf1858ce9d7fdb62240546'), 
    (3, 'default@gmail.com', '5294cef9f1bf1858ce9d7fdb62240546'),
    (4, 'jims@gmail.com', null), 
    (5, 'jims@gmail.com', null),
    (6, null, null),
    (7, null, null); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 如果只是为了去重,那么意义是一样的(Group by效率高)
    • group by应用的范围更广泛一些,如分组汇总,或者从聚合函数里筛选数
    • count,distinct和group by对null值的操作
      • distinct 会将选中的所有null视为一项

        格式:select distince a,b from talbleName
        使用:SELECT DISTINCT email,passwords FROM test_users WHERE 1 = 1 ,输出:
        在这里插入图片描述

      • group by 将选中的所有null视为一项

        格式:select a, b from tableName groupby a,b
        使用:SELECT email, passwords, COUNT(*) FROM test_users WHERE 1 = 1 GROUP BY email,passwords 输出:
        在这里插入图片描述

      • count 不会计算null值项,count(null)=0

        1.count(1)与count(*)得到的结果一致,包含null值。
        2.count(字段)不计算null值
        3.count(null)结果恒为0

        select count(*) from test_users
        union all 
        SELECT count(distinct email, passwords) FROM test_users
        union all 
        select count(*)  from (
        						  SELECT email,passwords
        						  FROM test_users
        						  group by email,passwords ) a;
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8

        在这里插入图片描述

    3.2 例子说明

    我们现在有一张dept_emp表共四个字段,分别是emp_no(员工编号),dept_no(部门编号),from_date(起始时间),to_date(结束时间),记录了员工在某一部门所处时间段,to_date等于9999-01-01的表示目前还在职。
    在这里插入图片描述
    我们现在想知道每个部门有多少名在职员工,步骤如下:

    • 筛选在职员工 where to_date=‘9999-01-01’;
    • 对部门进行分组group by dept_no
    • 对员工进行计数 count(emp_no)
      SELECT
        dept_no as 部门,
        count(emp_no) as 人数
      FROM
        dept_emp 
      WHERE
        to_date = '9999-01-01' 
      GROUP BY
        dept_no
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      在这里插入图片描述

    我们上一步分组之后得到的结果是部门编号,下一步我们可以通过departments去关联出部门名称,语句如下:

    • 筛选在职员工 where to_date=‘9999-01-01’;
    • 对部门进行分组group by dept_no
    • 对员工进行计数 count(emp_no),关联departments表找处部门名字
      SELECT
          (SELECT d.dept_name FROM departments d WHERE de.dept_no = d.dept_no) AS 部门,
          count(de.emp_no) AS 人数 
      FROM
          dept_emp de 
      WHERE
          de.to_date = '9999-01-01' 
      GROUP BY
          de.dept_no
      
      // ❌❌❌❌错误做法(dept_emp表没有部门名字)❌❌❌❌
      SELECT
          de.dept_name AS 部门,
          count( de.emp_no ) AS 人数 
      FROM
          dept_emp de 
      WHERE
          de.to_date = '9999-01-01' 
      GROUP BY
          de.dept_no
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20

    在这里插入图片描述

    4、having

    4.1 having和where的用法区别

    • having只能用在group by之后,对分组后的结果进行筛选(即,使用having的前提条件是分组)
    • where肯定在group by 之前,即也在having之前。
    • where后的条件表达式里不允许使用聚合函数,而having可以

    4.2 例子说明

    我们现在有一张dept_emp表共四个字段,分别是emp_no(员工编号),dept_no(部门编号),from_date(起始时间),to_date(结束时间),记录了员工在某一部门所处时间段,to_date等于9999-01-01的表示目前还在职。
    在这里插入图片描述

    • 已知每个部门人数都有了,如果我们想要进一步知道员工人数大于30000的部门是哪些?
      SELECT
          (SELECT d.dept_name FROM departments d WHERE de.dept_no = d.dept_no) AS 部门,
          count(de.emp_no ) AS 人数 
      FROM
          dept_emp de 
      WHERE
          de.to_date = '9999-01-01' 
      GROUP BY
          de.dept_no 
      HAVING  // 计算的是分组后,组内的总数
          count(de.emp_no ) > 30000 
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      在这里插入图片描述

    5、order by

    5.2 升序或降序排列

    • 根据输入的多个字段,按照升序或降序排列

      在这里插入图片描述

    5.2 按顺序去重时,order by 的列必须出现在 distinct 中

    • 出错代码
      在这里插入图片描述

    • 改正后的代码
      在这里插入图片描述

    • 讨论:若不使用Distinct关键字,则order by后面的字段不一定要放在seletc中
      在这里插入图片描述

  • 相关阅读:
    华为云云服务器评测|基于华为云云耀云服务器L实例开展性能评测,例如 MySQL、Clickhouse、Elasticsearch等等
    JavaSE——方法、递归
    LeetCode 2258. 逃离火灾:BFS
    艾美捷热转移稳定性检测试剂盒:简单、灵敏、均匀的荧光测定法
    【SpringBoot】12.SpringBoot整合Dubbo+Zookeeper
    JS高级 之 Promise 详解
    Android 图片裁剪并批量上传视频图片到阿里云OSS
    快速生成力扣链表题的链表,实现快速调试
    Kotlin初级【基本语法、数据类型、循环】
    GJB软件需求规格说明-编制指南
  • 原文地址:https://blog.csdn.net/qq_35091353/article/details/127634617