【新星计划】数据库 排名函数 初识

news2024/10/6 14:35:13

数据库 排名函数 初识

  • 查询排序
  • 初识排名函数
    • row_number()
    • rank()
    • dense_rank()
    • ntile()
    • percent_rank()
  • 开窗函数
    • 为聚合函数使用开窗函数
  • 小结

查询排序

在日常工作中,我们对所有需要的数据都会进行一个排序操作,以获得我们最需要的数据。

排序指令 order 虽然已经很强大了,支持多个列同时排序,但是,在复杂场景下,还是有些捉襟见肘,比如,我要找到最新发布的第11篇到第20篇文章。

在古早时代,我们需要进行三次排序,第一次,找出最新的20篇文章,第二次,对这20篇倒序排列,找出最早的10篇,然后对这10篇进行时间排序并输出。

select * 
from (
	select top 10 *
	from (
		select top 20 *
		from articles
		order by pub_time desc
	) a
	order by pub_time
) a
order by pub_time desc

mysql 在这方面还是不错的,用 limit 可以指定,所以sqlserver 在 2005 版本的时候,就追加了排名函数支持。

select * 
from (
	select *,row_number() over(order by pub_time desc) as sn 
	from article
) a
where sn between 11 and 20
order by sn

在输出信息里追加了一个排名序号列,mysql 表示这都不是事,我们自己也可以变量完成这个操作,所以 mysql 的排名函数支持就严重滞后了,直到 mysql 8才开始支持,比oracle 都要晚不少了。

CSDN 文盲老顾的博客,https://blog.csdn.net/superwfei

初识排名函数

在讲排名函数前,我们先用 leetcode 的第 180 题来模拟一下,在没有排名函数前,如果我们要实现这个查询,应该怎么做。

题目地址:https://leetcode.cn/problems/consecutive-numbers/

编写一个 SQL 查询,查找所有至少连续出现三次的数字。

而这个题目中,id 是连续的,相对来说还是简单了,咱们弄个 id 不连续的来看看,但保证是按 id 递增来判断是否是连续数字

with t (id,num) as (
	select 1,1
	union all select 2,1
	union all select 4,1
	union all select 5,2
	union all select 7,1
	union all select 8,2
	union all select 9,2
)
select * 
from t a
left join t b on b.id=(select top 1 id from t where id>a.id and a.num=b.num order by id)
left join t c on c.id=(select top 1 id from t where id>b.id and b.num=c.num order by id)

在这里插入图片描述
最后根据是否第三个表中有数据来判定是否连续。而如果连续数字较多,还需要进行排重。

当然,leetcode 的这个题目还是比较简单的,只要求输出3个以上连续数字的数是几,没有要求输出连续位置,最大连续数量等等内容。

那么,我们在使用排名函数的话,会出现什么结果呢?老顾的文章《row_number 和 cte 使用实例:求不连续的分段结果》就是这样一种类似的需求下,写出来的一个解答方式。

还是用 leetcode 这个题目做个示例,不过数据我们扩充下,解答也扩充下。那么,先给出一个解答,再看排名函数。

with t (id,num) as (
	select 1,1
	union all select 2,1
	union all select 3,1
	union all select 4,1
	union all select 5,2
	union all select 7,1
	union all select 8,2
	union all select 9,2
	union all select 10,2
	union all select 12,1
	union all select 13,1
	union all select 14,1
	union all select 15,1
)
select num 连续三次以上数字,count(0) 连续次数,min(id) 最小id,max(id) 最大id
from (
    select *
        ,row_number() over(order by id) rid 
        ,row_number() over(partition by num order by id) nid
    from t
) a
group by (rid - nid),num
having(count(0) > 2)

row_number()

在这个题目的解答中,我们使用了 row_number,这就是一个排名函数,后边跟随的 over ,叫做开窗函数,语法百度一下大把的,就不细说了。

这里解释下刚才的指令的思路。

1、先按照 id 使用排名函数分配一个连续序号,保证在 id 或其他为依据的数据,在不连续的情况下也可正常使用。
2、二次使用排名函数,但是追加 partition 运算,即数据分区,使得每个相同的数字,各自独立再得到另外一个序号
3、两个序号相减。。。。数字相同,表示连续
4、按照相减结果分组统计,即可得到连续次数,连续开始位置,连续结束位置灯信息。
5、只需限定出现次数,可以方便的得到任意连续次数或及以上的结果,而不用每多一个数字就再追加一个join了

order 可以使用系统函数或变量,使其返回相同的值,则不会影响现有排序,比如 order by @@roucount,老顾以这个特性写过一篇文章《使用 row_number 获取实际返回行的行号》

rank()

rank 和 row_number 差不多,不过 row_number 对于相同的值,给定的序号也是不同的,每个序号只会出现一次,而 rank 对于相同的值,给出的序号也是相同的。最常见的场景就是,如果出现并列第一,那么就没有第二名,直接第三名的样子。

dense_rank()

这个和 rank 就非常非常相似了,不过这个分配的序号也是连续的,并列第一,并列第二,并列第三等等,不会跳过去了。

leetcode 185 就是一个典型用 dense_rank 解决起来非常简单的问题。

题目地址:https://leetcode.cn/problems/department-top-three-salaries/,有兴趣的小伙伴可以去实操一下。

ntile()

这个函数,则略有差异了,需要指定一个参数了,比如 ntile(3),表示将数据分成三份,所影响的行各自分配到序号1、2、3,他会尽量平均分配的,同时,改分配也支持分区 partition。

percent_rank()

最特殊的一个排名函数来了,这次返回的不是自然数了,而是一个浮点数。按名称也可以看出,这个是一个百分比结果 percent。而且,这个结果的值是从零到一,且包含零和一哦。

需要注意的一点是,由排名函数得到的值,在本层中无法参与到运算中,需要在外边套一层查询指令。但排名函数本身的运算是可以参与到 order 中的。
在这里插入图片描述

开窗函数

刚才已经讲过了,over 并不是排名函数,而是为了支持排名函数实现,所使用的另外一个类型的函数,这个才叫开窗函数,目前老顾仅仅知道 over 这一个。

而刚刚所用到的 order 排序也好,分区 partition 也好,都是属于开窗函数的,而不是排名函数。

再有,开窗函数中的排序仅影响排名序号,在无查询指令特意指定排序的情况下,会以最后一个 over 中的排序为依据作为最终排序结果,如果自行指定了 order 则忽略 over 中的 order。

为聚合函数使用开窗函数

而开窗函数除了支持使用排名函数之外,其实,还支持聚合函数,比如 sum,这个用法老顾也是刚从问答里见过不久,暂时没有总结出特别好的用法和规律。这里给出一个示例,了解一下。老顾自己也还需要补课,这个就不展开来说了。

with t (id,num) as (
	select 1,1
	union all select 2,1
	union all select 3,1
	union all select 4,1
	union all select 5,2
	union all select 7,1
	union all select 8,2
	union all select 9,2
	union all select 10,2
	union all select 12,1
	union all select 13,1
	union all select 14,1
	union all select 15,1
)
select *
		,sum(num) over(order by id)
from t

在这里插入图片描述

with t (id,num) as (
	select 1,1
	union all select 2,1
	union all select 3,1
	union all select 4,1
	union all select 5,2
	union all select 7,1
	union all select 8,2
	union all select 9,2
	union all select 10,2
	union all select 12,1
	union all select 13,1
	union all select 14,1
	union all select 15,1
)
select *
    ,sum(num) over(order by id)
	,avg(convert(float,num)) over(order by id)
from t

在这里插入图片描述

小结

本文我们粗略的了解了一下排名函数、开窗函数以及附带提了一嘴的聚合函数。在实际工作中,灵活使用排名函数,会发现很多问题变得不再是问题了。

而且,mysql 由于实现排名函数和开窗函数的时机已经太晚了,所以,估计这些东西都是借鉴的 mssql ,用法,语法上基本完全一致,不存在跨数据库学习差异问题。

另外,对于排名函数的使用,解决了原有 group 分组时,部分字段不在分组依据时,无法列出的问题。当我们使用排名函数,以原来的分组作为分区时,就可以方便的得到原有需要的数据。。。嗯,是在没有聚合函数的情况下。有聚合运算时另说。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unreal Niagara粒子入门1

记录下学习Niagara粒子的过程,这次调的是比较简单的一个效果: 使用了随粒子生命的缩放、打开速率解算、基本的发射器和Niagara容器。 1.创建Niagara Niagara中,发射器和NiagaraSystem文件是可以分开创建的: 通常直接点Niagara…

GPT-2(Transformer Decoder)的TensorFlow实现(附源码)

文章目录 一、GPT2实现步骤二、源码 一、GPT2实现步骤 机器学习模型的开发实现步骤一般都包含以下几个部分:   1. 遵照模型的网络架构,实现每一层(Layer/Block)的函数;   2. 将第1步中的函数组合在一起&#xff0c…

微信小程序nodejs+vue校园快递代拿系统uniapp校园互助系统

语言 node.js 框架:Express 前端:Vue.js 数据库:mysql 数据库工具:Navicat 开发软件:VScode 平台旨在解决目前大学生找人帮忙,难,慢,不可靠以及想兼职同学找不到好的平台的问题。对于招人帮忙的…

应急演练脚本编写的几个步骤

应急演练是一项非常重要的活动,对于保障企业的安全和稳定运行至关重要。而一个完整的应急演练需要编写一个详细的脚本来指导演练过程。以下是应急演练脚本编写的几个步骤。 定义演练场景 首先,需要定义演练场景,这将决定演练的目标和方向。在…

美国原装二手 SR560 低噪声电压前置放大器

Stanford Research SR560低噪声电压前置放大器 ​Stanford Research SR560 是一款高性能、低噪声前置放大器,适用于各种应用,包括低温测量、光学检测和音频工程。 SR560 具有一个具有 4 nV/√Hz 输入噪声和 100 MΩ 输入阻抗的差分前端。完整的噪声系数…

三招教你图片文字转语音怎么转

随着数字化时代的到来,人们对于数字信息的获取和处理需求越来越大,而图片文字转语音技术正是为了满足这一需求而诞生的。这项技术不仅可以辅助视力障碍者,让他们能更轻松地获取信息和理解内容,而且也可以帮助正在学习外语的人们练…

Menards EDI对接流程

Menards是一家美国的家居建材零售商,成立于1962年,总部位于美国威斯康星州的伊甸谷市。该公司经营各种家居建材产品,包括木材、地板、墙纸、厨房卫浴用品等,并拥有超过300家门店,分布在美国中西部和北部地区。Menards的…

2023智能座舱新趋势洞察

两年一度的上海车展于4月底正式落幕,怿星科技市场总监老崔率团队奔赴考察,经过多日分析整理,围绕车展发布车型为核心,制作了怿星科技2023智能座舱趋势洞察报告,现将报告分享如下。 01 车展简述 汽车行业进入新时代 本…

DVB-S中卫星通信系统的基带仿真(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 ​数字视频广播(DVB)在卫星通信数字多媒体业务领域应用广泛,其一般采用MPEG-2编码、数字传输和纠错处理等通用技术,然而,当第三方…

LeetCode 117. 填充每个节点的下一个右侧节点指针 II

117. 填充每个节点的下一个右侧节点指针 II 描述 给定一个二叉树: struct Node {int val;Node *left;Node *right;Node *next; }填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 …

csgo搬砖人必知:未来csgo饰品会一路走低吗?市场回暖到底还要多久?

csgo搬砖人必知:未来csgo饰品会一路走低吗?市场回暖到底还要多久? 最后一届巴黎major终于落下帷幕,Vitality小蜜蜂2-0战胜GL成功赢下本次Major冠军,也是首次夺得Major冠军!有人欢喜有人忧啊,cs…

Phaser笔记文档阅读-Working with Phaser, TypeScript and webpack – step 1

首先得安装好npm和node.js。 创建一个空文件夹如:phaserwebpack,这里我使用webstorm打开,打开终端: 运行: npm init -y 执行上面的命令成功后会自动创建package.json文件。随后安装phaser: npm install…

常用性能测试工具选择所需要考虑的因素

在软件开发和应用中,性能问题是一个非常普遍的问题。进行性能测试已经成为了软件开发和应用必不可少的一步。而性能测试工具就是进行性能测试的关键。市面上有许多种不同类型的性能测试工具,如何选择合适的工具呢?以下是一些常用性能测试工具…

SpringCloud(注册中心)

分布式架构与微服:【restfu分格(入参的分格)---rest分格(请求的分格)】 微服务: 单体架构的应用场景: 微服务的应用场景: 上百个服务---服务于服务之间是有依赖关系的 什么是spring…

Shell运维实战1-核心与数值计算

目录 Shell 初步入门Shell 分类幻数注释 Shell 核心与实践变量引号输出特殊变量特殊状态变量bash 内置变量命令变量子串特殊扩展变量 Shell 变量数值计算实践基本算术运算符双小括号letexprbcawkread Shell 初步入门 Shell 分类 对于 Unix/Linux 两种系统,shell 主…

导入/导出 OpenAPI 不再是问题,这个开源管理工具可以!

导入 OpenAPI 插件 支持导入 OpenAPI 3.0 版本的文件,如果您使用 Swagger1.0/2.0,可以访问这个在线地址 转换为 3.0 再导入。 使用 导入功能有多个入口,你可以在 API 分组处点击加号导入 API: 也可以在设置页面导入 导出 OpenAP…

第17章_触发器

第17章_触发器 在实际开发中,我们经常会遇到这样的情况:有 2 个或者多个相互关联的表,如商品信息和库存信息分别存放在 2 个不同的数据表中,我们在添加一条新商品记录的时候,为了保证数据的完整性,必须同时…

Android和iOS双端赞奇超级云盘APP公测版正式上线!

赞奇云工作站自发布以来,经过层层迭代和升级,以云工作站、赞奇超级云盘、软件中心、云渲染等功能,更高效地整合打通各行设计业务全流程,实现云上数字内容创作的完美呈现,取得了广大用户的喜爱和认可。 现在&#xff0…

一个月节省40万核,企业级云资源分析与成本优化平台

Crane简介 Crane是一个基于 FinOps 的云资源分析与成本优化平台,是在保证客户应用运行质量的前提下实现极致的降本。 Crane 已经在腾讯内部自研业务实现了大规模落地,部署数百个 K8s 集群、管控 CPU 核数达百万,在降本增效方面取得了阶段性成…

数据驱动运营增长

利用数据来分析、优化和提升产品或服务的各个方面,从而实现业务目标的方法叫数据驱动运营增长。用好数据,在运营中能精准地定位用户需求、痛点、偏好和行为,细分用户群体以提供个性化的产品或服务,精细化地管理和优化每一个环节和…