根据mysql的执行顺序来写select

过滤顺序指的是mysql的逻辑执行顺序,个人觉得我们可以按照执行顺序来写select查询语句。

目录

  • 一、执行顺序
  • 二、小tips
  • 三、案例
    • 第一轮查询:统计每个num的出现次数
    • 第二轮查询:计算**最多次数**
    • 第三轮查询:找到所有出现次数为最多次数的所有数字,并找到这些数字中的最大值
    • 计算结果展示:
    • 补充说明
  • 四、结语

一、执行顺序

  1. FROM子句
    这是执行的第一步,数据库系统读取指定的表和视图,这是后续所有操作的基础。

  2. JOIN
    如果涉及多个表,则基于JOIN条件,将表中的行组合起来。

  3. WHERE子句:对行的过滤
    接下来,数据库系统会过滤掉不符合WHERE条件的行。这是在聚集函数(如COUNT、SUM等)应用之前进行的,因此只作用于原始数据。
    WHERE 子句后面不能直接接聚合函数(如 COUNT(), MAX(), SUM() 等)。WHERE 子句用于指定从基础数据表中选择哪些行的标准,这些标准必须是能够对每一行单独评估的布尔表达式。由于聚合函数是在行群(group)上操作的,而不是单独的行上,所以它们不能直接在 WHERE 子句中使用。
    总之,是对原始数据的每一行进行操作!!!没法联系多行进行判断,所以不能用聚集函数!!!!!

  4. GROUP BY子句
    将之前得到的结果集按照指定的列值进行分组,为聚集函数(如COUNT、SUM等)的应用做准备。

  5. HAVING子句:对组的过滤
    与WHERE类似,但它是在聚集函数应用后对分组的结果进行过滤,相比于where,涉及到了多行,所以可以使用聚集函数。
    可以简单理解成:where过滤掉行,having过滤掉组,均是接的布尔表达式。
    没有 GROUP BY 的上下文中单独使用 HAVING 是不常见的,而且可能不被所有SQL数据库支持。

  6. SELECT
    选取指定的列。
    如果使用了聚集函数,那么非聚集列必须出现在GROUP BY子句中,除非它们在聚集函数内部。比如使用了select max(num),它将从每一组中找到一个最大的num,而不是整张表中找
    关于增加一列:根据条件显示内容

    casewhen 条件1(布尔表达式) then 满足条件1要展示的结果when 条件2(布尔表达式) then 不满足条件1满足条件2的结果else 都不满足的结果
    end as 别名
    

二、小tips

  1. 子查询作为数据源,必须有别名,如果是在where、having语句中,则不拥有。

  2. 聚集函数嵌套的问题:
    不允许直接嵌套聚合函数:聚合函数(如AVG(), SUM(), MAX()等)通常不允许直接嵌套使用。也就是说,一个聚合函数的结果不能直接成为另一个聚合函数的输入,如MAX(COUNT(column))是不允许的。
    允许聚合结果被其他函数处理:聚合函数的结果可以被其他非聚合函数处理,如ROUND(AVG(column), 2)是允许的。这是因为ROUND函数在这里不是在进行聚合操作,而是在对聚合操作的单一结果值进行格式化或转换。

三、案例

假设目前数据库有一个表nums:

CREATE table nums(num INTEGER
);

插入样本数据:

insert into nums(num)
values(8),(8),(3),(3),(1),(2),(5),(6);

任务:找到nums表中出现次数最多的数字,如有多个,展示最大的结果。

下面开始按照过滤顺序具体实现:
我们将任务拆分为三轮:
第一轮:统计每个num的出现次数
第二轮:计算最多次数
第三轮:找到所有出现次数为最多次数的所有数字,并找到这些数字中的最大值
在每一轮中,将按照执行顺序一步步书写语句:

  1. FROM
  2. JOIN
  3. WHERE
  4. GROUP BY
  5. HAVING
  6. SELECT
  7. DISTINCT
  8. ORDER BY
  9. LIMIT / OFFSET

强调一下,每一步操作都是基于前面执行的结果再操作的,比如where就只会对原始from和join后的结果对行进行过滤,不会对group by的结果做过滤,这一点很重要!!!

第一轮查询:统计每个num的出现次数

  1. FROM:找到表nums
	from nums
  1. JOIN
    不需要涉及多个表,略。
  2. WHERE
    不需要过滤掉任何行,所以略。
  3. GROUP BY
    需要找到每个数字出现的次数,自然需要分组,根据num分组:
	from numsgroup by num
  1. HAVING
    不需要略掉任何组,所以略。
  2. SELECT
    需要得到统计结果:
	select count(num) as frequencyfrom numsgroup by num

这里起一个别名,因为后续查询里,这个数字需要被用到,所以记得取别名
7. DISTINCT

8. ORDER BY

9. LIMIT / OFFSET

第二轮查询:计算最多次数

  1. FROM
    这里需要找到出现次数中的最大值,所以第一轮查询的结果,将作为这一轮查询的数据源。
from(select count(num) as frequencyfrom numsgroup by num) table_temp

根据前面小tips的第一条,子查询的结果如果是作为数据源,那么一定要取别名,否则会报错,别名前面可加as,也可以不加。
2. JOIN
不需要,略。
3. WHERE
虽然需要找到最高次数,看似可以在这一步对行级过滤,但是where对每一行操作时,只能看到当前行的数据,所以它不能使用max这种聚集函数得到全表的最大值,所以这一步略。
4. GROUP BY
不需要再分组了,略。
5. HAVING
没有分组了,所以它略。
6. SELECT
找到最大值,所以增加select max(frequency)

select max(frequency)from(select count(num) as frequencyfrom numsgroup by num) as table_temp
  1. DISTINCT
  2. ORDER BY
  3. LIMIT / OFFSET

第三轮查询:找到所有出现次数为最多次数的所有数字,并找到这些数字中的最大值

  1. FROM
    是对全表进行查询,找到出现次数为最大次数的结果,所以数据源是全表。
from nums
  1. JOIN
    略。
  2. WHERE
    无法对原始数据直接做过滤,因为此时还不能从第一步得到的结果中知道每个数字的次数,所以略。
  3. GROUP BY
    为得到次数,再一次做分组
from nums
group by num
  1. HAVING
    对每一组做过滤,保留次数等于最大次数的组,判断的条件是count(num)=最大次数,最大次数为第二轮查询的结果,所以将结果嵌套进来:
from nums
group by num
having count(num)=(
select max(frequency)from(select count(num) as frequencyfrom numsgroup by num) as table_temp
)
  1. SELECT
    目前得到了多个组结果,每个组的数字都满足出现次数等于最大次数,将数字选出来,即使用select num
select num
from nums
group by num
having count(num)=(
select max(frequency)from(select count(num) as frequencyfrom numsgroup by num) as table_temp
)
  1. DISTINCT
    不需要去重,略。
  2. ORDER BY
    为了找到最大值的结果,对目前的num结果降序,增加order by num desc
select num
from nums
group by num
having count(num)=(
select max(frequency)from(select count(num) as frequencyfrom numsgroup by num) as table_temp
)
order by num desc
  1. LIMIT / OFFSET
    选择排序第一的结果limit 1,它是最大值
select num
from nums
group by num
having count(num)=(
select max(frequency)from(select count(num) as frequencyfrom numsgroup by num) as table_temp
)
order by num desc
limit 1

计算结果展示:

在这里插入图片描述

补充说明

关于为什么要拆分步骤一和步骤二,为什么不直接写:

	select max(count(num))from numsgroup by num

会报错,原因见小tips的第二点

四、结语

我觉得我应该说清楚了where和having的区别了,也讲清楚了聚集函数为什么不能再where中使用🤔,按照执行顺序来写select语句,逻辑很清晰,不容易出错。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/299042.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据库】主流数据库及其常用工具简单科普

主流数据库及其常用工具 数据库分类关系型数据库(RDBMS)非关系型数据库(NoSQL)混合型数据库(Hybrid Databases)对象关系数据库(ORDBMS)多维数据库(Multidimensional Data…

InterliJ IDEA基本设置

安装好idea后,将软件打开,可以进行基础设置 1.打开软件,先安装插件-汉化包(不推荐,最好使用英文版),本次我们使用汉化版本完成基本设置,后期希望大家适应英文版的开发环境。&#x…

05-延迟任务精准发布文章

延迟任务精准发布文章 1)文章定时发布 2)延迟任务概述 2.1)什么是延迟任务 定时任务:有固定周期的,有明确的触发时间延迟队列:没有固定的开始时间,它常常是由一个事件触发的,而在这个事件触发之后的一段时间内触发…

docker + miniconda + python 环境安装与迁移(详细版)

本文主要列出从安装dockerpython环境到迁移环境的整体步骤。windows与linux之间进行测试。 简化版可以参考:docker miniconda python 环境安装与迁移(简化版)-CSDN博客 目录 一、docker 安装和测试 二、docker中拉取miniconda&#xff…

Java数据结构队列

队列(Queue) 概念 队列的使用 注意:Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。 import java.util.LinkedList; import java.util.Queue;public class Test {public static void main(String[]…

数据挖掘中的PCA和KMeans:Airbnb房源案例研究

目录 一、PCA简介 二、数据集概览 三、数据预处理步骤 四、PCA申请 五、KMeans 聚类 六、PCA成分分析 七、逆变换 八、质心分析 九、结论 十、深入探究 10.1 第 1 步:确定 PCA 组件的最佳数量 10.2 第 2 步:使用 9 个组件重做 PCA 10.3 解释 PCA 加载和特…

路由器拨号失败解决方法

目录 一、遇到问题 二、测试 三、解决方法 (一)路由器先单插wan口设置 (二)mac地址替换 (三)更改路由器DNS 一、遇到问题 1 .在光猫使用桥接模式,由路由器进行拨号的时候,出现…

电子商务平台中大数据的应用|主流电商平台大数据采集API接口

(一)电商平台物流管理中大数据的应用 电商平台订单详情订单列表物流信息API接口应用 电子商务企业对射频识别设备、条形码扫描设备、全球定位系统及销售网站、交通、库存等管理软件数据进行实时或近实时的分析研究,提高物流速度和准确性。部分电商平台已建立高效的物流配送网…

windows程序设计课程作业-1

目录 1、作业内容 2、主要思路 (1)写接口 (2)写类具体实现接口 (3)声明委托 (4)创建实例 (5)实例化委托 3、难点分析 1)想明白接口的作用 2)委托的作用 4、实现代码 5、运行结果 1、作业内容 使用 C# 编码(涉及类、接口、委托等关…

5.5G,只比6G少0.5G

5.5G成为通信行业2024年开年的一大焦点。提到5.5G,多出来的0.5G又是啥?为什么不直接迈向6G时代?今天我们一探究竟! “0.5G”,现在与未来的桥梁 2021年,国际标准组织3GPP为通信技术的进一步发展定义了新的里…

【SCI绘图】【曲线图系列1 python】绘制扫描点平滑曲线图

SCI,CCF,EI及核心期刊绘图宝典,爆款持续更新,助力科研! 本期分享: 【SCI绘图】【曲线图1 python】绘制扫描点平滑曲线图 1.环境准备 python 3 import numpy as np import pandas as pd import proplot …

爱上数据结构:二叉树的基本概念

​ ​ 🔥个人主页:guoguoqiang. 🔥专栏:数据结构 ​ 一、树的基本概念 1.概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做树是因 为它看起…

list的使用

前言 我们前面已经对string和vector进行了学习使用,以及对他们的底层进行了模拟实现!本期我们继续学习STL的另外一个容器---list。 本期内容介绍 什么是list? list的常用接口 什么是list? 还是来看看官方的文档说明! 这里通过…

网络网络层之(3)IPv6地址

网络网络层之(3)IPv6协议 Author: Once Day Date: 2024年4月2日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文档可参考专栏:通信网络技术_Once-Day的…

RabbitMQ3.13.x之十_流过滤的内部结构设计与实现

RabbitMQ3.13.x之十_流过滤的内部结构设计与实现 文章目录 RabbitMQ3.13.x之十_流过滤的内部结构设计与实现1. 概念1. 消息发布2. 消息消费 2. 流的结构1. 在代理端进行过滤2. 客户端筛选3. JavaAPI示例4. 流过滤配置5. AMQP上的流过滤6. 总结 3. 相关链接 1. 概念 流过滤的思…

实战篇04:获取用户详细信息

实战篇04:获取用户详细信息 一、接口信息 1.1 基本信息 请求路径:/user/userInfo 请求方式:GET 接口描述:该接口用于获取当前已登录用户的详细信息 1.2 请求参数 无 1.3 响应数据 响应数据类型:application/json …

基于圆柱体镜子和光线跟踪实现镜反射观测全景观图的matlab模拟仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 光线与圆柱镜面的交点计算: 反射光线计算: 全景图坐标转换: 5.完整程序 1.程序功能描述 基于圆柱体镜子和光线跟踪实现镜反射观测全景观图.模拟的场景…

SV学习笔记(七)

文章目录 类型转换写在前面动态转换子类句柄赋值于父类句柄父类句柄转换为子类句柄 虚方法写在前面非虚函数的调用虚函数的调用虚方法的建议为什么使用虚方法 对象拷贝写在前面赋值和拷贝总结 回调函数写在前面实例完成回调函数功能需要三步: 参数化类写在前面实现一…

如何使用极狐GitLab Maven 仓库?

本文作者:徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了如何使用极狐GitLa…

TPAMI:计算机学会像人脑一样“听话”了!清华团队实现混合语音分离技术突破

我们的大脑在处理声音信息时有一个特长:可以将注意力集中在感兴趣的对话或声音上,忽略其它无关的声音或者噪音。我们每天都在不知不觉地运用这种特长,在通勤的地铁上、嘈杂的餐厅里,广播声、音乐声、多人同时说话的声音&#xff0…