MySQL 下 ROW_NUMBER / DENSE_RANK / RANK 的实现

从零到一:掌握 dense_rank() 函数在MySQL与Hive中的实战应用 本文详细解析了dense_rank()函数在MySQL与Hive中的实战应用,重点介绍了其在分组排序场景下的优势与实现方法。通过电商销售排名等实际案例,展示了如何利用dense_rank()实现连续排名且不跳号的需求,并提供了性能优化与常见错误排查指南,帮助开发者高效处理数据排名问题。 阅读详情

来自:http://blog.sina.com.cn/s/blog_562b10b901011c17.html

CREATE TABLE test_rownum (
ID int,
Ke CHAR(1),
val INT
);

INSERT INTO test_rownum
SELECT 1, 'A', 1 UNION ALL
SELECT 2, 'A', 2 UNION ALL
SELECT 3, 'A', 3 UNION ALL
SELECT 4, 'B', 1 UNION ALL
SELECT 5, 'B', 2 UNION ALL
SELECT 6, 'B', 1 UNION ALL
SELECT 7, 'C', 3 UNION ALL
SELECT 8, 'C', 2 UNION ALL
SELECT 9, 'C', 2;


rownum 用于显示序号
ID 字段用于 标记 原有的序号位置.


普通的处理
等价于 ROW_NUMBER() OVER (ORDER BY ke, val)

SELECT
@rownum:=@rownum+1 AS rownum,
id,
ke,
val
FROM
(SELECT @rownum:=0) r,
test_rownum
ORDER BY
ke, val;

+--------+------+------+------+
| rownum | id | ke | val |
+--------+------+------+------+
| 1 | 1 | A | 1 |
| 2 | 2 | A | 2 |
| 3 | 3 | A | 3 |
| 4 | 4 | B | 1 |
| 5 | 6 | B | 1 |
| 6 | 5 | B | 2 |
| 7 | 8 | C | 2 |
| 8 | 9 | C | 2 |
| 9 | 7 | C | 3 |
+--------+------+------+------+
9 rows in set (0.00 sec)

PARTITION 的处理
等价于 ROW_NUMBER() OVER (PARTITION BY ke ORDER BY val)

SELECT
CASE
WHEN @ke != ke THEN @rownum:= 1
ELSE @rownum:= @rownum + 1
END AS rownum,
id,
@ke := ke AS ke,
val
FROM
(SELECT @ke:='') k,
(SELECT @rownum:=0) r,
test_rownum main
ORDER BY
ke, val;

+--------+------+------+------+
| rownum | id | ke | val |
+--------+------+------+------+
| 1 | 1 | A | 1 |
| 2 | 2 | A | 2 |
| 3 | 3 | A | 3 |
| 1 | 4 | B | 1 |
| 2 | 6 | B | 1 |
| 3 | 5 | B | 2 |
| 1 | 8 | C | 2 |
| 2 | 9 | C | 2 |
| 3 | 7 | C | 3 |
+--------+------+------+------+
9 rows in set (0.00 sec)


RANK DENSE_RANK 的处理
等价于 RANK() OVER (PARTITION BY ke ORDER BY val)

等价于 DENSE_RANK() OVER (PARTITION BY ke ORDER BY val)

SELECT
CASE
WHEN @ke != ke THEN @rownum:= 1
ELSE @rownum:= @rownum + 1
END AS ROW_NUMBER,
CASE
WHEN @ke != ke THEN @rank:= 1
WHEN @val = val THEN @rank
ELSE @rank:= @rownum
END AS RANK,
CASE
WHEN @ke != ke THEN @dense_rank:= 1
WHEN @val = val THEN @dense_rank
ELSE @dense_rank:= @dense_rank + 1
END AS DENSE_RANK,
id,
@ke := ke AS ke,
@val := val AS val
FROM
(SELECT @ke:='') k,
(SELECT @val:=0) v,
(SELECT @rownum:=0) r,
(SELECT @rank:=0) r2,
(SELECT @dense_rank:=0) d,
test_rownum main
ORDER BY
ke, val;


+------------+------+------------+------+------+------+
| ROW_NUMBER | RANK | DENSE_RANK | id | ke | val |
+------------+------+------------+------+------+------+
| 1 | 1 | 1 | 1 | A | 1 |
| 2 | 2 | 2 | 2 | A | 2 |
| 3 | 3 | 3 | 3 | A | 3 |
| 1 | 1 | 1 | 4 | B | 1 |
| 2 | 1 | 1 | 6 | B | 1 |
| 3 | 3 | 2 | 5 | B | 2 |
| 1 | 1 | 1 | 8 | C | 2 |
| 2 | 1 | 1 | 9 | C | 2 |
| 3 | 3 | 2 | 7 | C | 3 |
+------------+------+------------+------+------+------+
9 rows in set (0.00 sec)

=======================================================
两表关联情况下的测试.

CREATE TABLE test_rownum_main (
ID int,
Ke CHAR(1)
);

CREATE TABLE test_rownum_sub (
KeID int,
val INT
);

INSERT INTO test_rownum_main
SELECT 1, 'A' UNION ALL
SELECT 2, 'B' UNION ALL
SELECT 3, 'C';

INSERT INTO test_rownum_sub
SELECT 1, 1 UNION ALL
SELECT 1, 2 UNION ALL
SELECT 1, 3 UNION ALL
SELECT 2, 1 UNION ALL
SELECT 2, 2 UNION ALL
SELECT 2, 1 UNION ALL
SELECT 3, 3 UNION ALL
SELECT 3, 2 UNION ALL
SELECT 3, 2;


普通的处理
等价于 ROW_NUMBER() OVER (ORDER BY ke, val)

SELECT
@rownum:=@rownum+1 AS rownum,
main.id,
main.ke,
sub.val
FROM
test_rownum_main main
JOIN test_rownum_sub sub
ON (main.ID = sub.KeID),
(SELECT @rownum:=0) r
ORDER BY
ke, val;

+--------+------+------+------+
| rownum | id | ke | val |
+--------+------+------+------+
| 1 | 1 | A | 1 |
| 2 | 1 | A | 2 |
| 3 | 1 | A | 3 |
| 4 | 2 | B | 1 |
| 6 | 2 | B | 1 |
| 5 | 2 | B | 2 |
| 8 | 3 | C | 2 |
| 9 | 3 | C | 2 |
| 7 | 3 | C | 3 |
+--------+------+------+------+
9 rows in set (0.00 sec)

rownum 顺序不满足预期结果了。
可能是因为执行关联的时候, 就把 @rownum 计算了。

修改SQL语句.

SELECT
@rownum:=@rownum+1 AS rownum,
id,
ke,
val
FROM
(SELECT @rownum:=0) r,
(
SELECT
main.id,
main.ke,
sub.val
FROM
test_rownum_main main
JOIN test_rownum_sub sub
ON (main.ID = sub.KeID)
) subQuery
ORDER BY
ke, val;

+--------+------+------+------+
| rownum | id | ke | val |
+--------+------+------+------+
| 1 | 1 | A | 1 |
| 2 | 1 | A | 2 |
| 3 | 1 | A | 3 |
| 4 | 2 | B | 1 |
| 5 | 2 | B | 1 |
| 6 | 2 | B | 2 |
| 7 | 3 | C | 2 |
| 8 | 3 | C | 2 |
| 9 | 3 | C | 3 |
+--------+------+------+------+
9 rows in set (0.00 sec)

PARTITION 的处理
等价于 ROW_NUMBER() OVER (PARTITION BY ke ORDER BY val)

SELECT
CASE
WHEN @ke != ke THEN @rownum:= 1
ELSE @rownum:= @rownum + 1
END AS rownum,
id,
@ke := ke AS ke,
val
FROM
(SELECT @ke:='') k,
(SELECT @rownum:=0) r,
(
SELECT
main.id,
main.ke,
sub.val
FROM
test_rownum_main main
JOIN test_rownum_sub sub
ON (main.ID = sub.KeID)
) subQuery
ORDER BY
ke, val;

+--------+------+------+------+
| rownum | id | ke | val |
+--------+------+------+------+
| 1 | 1 | A | 1 |
| 2 | 1 | A | 2 |
| 3 | 1 | A | 3 |
| 1 | 2 | B | 1 |
| 2 | 2 | B | 1 |
| 3 | 2 | B | 2 |
| 1 | 3 | C | 2 |
| 2 | 3 | C | 2 |
| 3 | 3 | C | 3 |
+--------+------+------+------+
9 rows in set (0.00 sec)


DENSE_RANK 的处理

RANK 的处理
等价于 DENSE_RANK() OVER (PARTITION BY ke ORDER BY val)

等价于 RANK() OVER (PARTITION BY ke ORDER BY val)

SELECT
CASE
WHEN @ke != ke THEN @rownum:= 1
ELSE @rownum:= @rownum + 1
END AS ROW_NUMBER,
CASE
WHEN @ke != ke THEN @rank:= 1
WHEN @val = val THEN @rank
ELSE @rank:= @rownum
END AS RANK,
CASE
WHEN @ke != ke THEN @dense_rank:= 1
WHEN @val = val THEN @dense_rank
ELSE @dense_rank:= @dense_rank + 1
END AS DENSE_RANK,
id,
@ke := ke AS ke,
@val := val AS val
FROM
(SELECT @ke:='') k,
(SELECT @val:=0) v,
(SELECT @rownum:=0) r,
(SELECT @rank:=0) r2,
(SELECT @dense_rank:=0) d,
(
SELECT
main.id,
main.ke,
sub.val
FROM
test_rownum_main main
JOIN test_rownum_sub sub
ON (main.ID = sub.KeID)
) subQuery
ORDER BY
ke, val;

+------------+------+------------+------+------+------+
| ROW_NUMBER | RANK | DENSE_RANK | id | ke | val |
+------------+------+------------+------+------+------+
| 1 | 1 | 1 | 1 | A | 1 |
| 2 | 2 | 2 | 1 | A | 2 |
| 3 | 3 | 3 | 1 | A | 3 |
| 1 | 1 | 1 | 2 | B | 1 |
| 2 | 1 | 1 | 2 | B | 1 |
| 3 | 3 | 2 | 2 | B | 2 |
| 1 | 1 | 1 | 3 | C | 2 |
| 2 | 1 | 1 | 3 | C | 2 |
| 3 | 3 | 2 | 3 | C | 3 |
+------------+------+------------+------+------+------+
9 rows in set (0.00 sec)


智能体异常行为检测-基于行为序列的异常模式识别技术【附代码】 在多智能体系统(Multi-Agent Systems, MAS)中,智能体之间的行为协调与自主决策是系统稳定运行的关键。然而,当某个智能体因策略偏移、环境变化或潜在攻击而出现**异常行为(Abnormal Behavior)**时,整个系统可能陷入混乱或崩溃。 阅读详情

相关推荐

手把手教你绕过网易易盾验证码:滑块、点选、语序全攻略

本文深度解析了以网易易盾为代表的现代验证码技术,重点探讨了滑块、点选、语序及空间推理等交互式验证码的工作原理与对抗策略。文章从行为验证和空间推理的核心逻辑出发,剖析了验证码交互的数据流与关键参数,并提供了模拟人类行为轨迹、维护设备指纹等工程实践方法,旨在帮助开发者在合规前提下设计更健壮的自动化流程。

3c4x5z6v7b的博客 704

Mysql常用函数之Rank 排名函数

mysql中的排名函数 主要介绍一下mysql里面的排名函数,涉及到的函数有以下几个: rank()、dense_rank()、row_number() 1、准备工作 建立一个rank表: create table rank( id int(10) not null primary key, name varchar(20) not null, score int(10) not null ); 插入一些数据: insert into rank values(1,'a',100); insert i

weixin_42272869的博客 3万+

Docker “docker login“ 失败? 登录阿里云镜像仓库仓库 unauthorized: authentication required

文章目录听说你 login fail?来,让我们解决一下!登录,撒花 听说你 login fail? 美滋滋的在服务器上安装完成Docker应用,开始配置阿里云镜像加速?然后被阿里云官方文档蹂躏?别急别急,让我来拯救你。 我们先来看看 阿里云官方文档 Docker镜像基本操作: 好家伙,emmm… 上来直接就Login Succeeded,这不简直so easy?我们也来照着操作操作: docker@default-online:~$ docker login registry.cn-hangzhou.a

zhuzicc的博客 1万+

SQL Server 排序函数 ROW_NUMBER、RANK、DENSE_RANK、INTERSECT、UNION、UNION ALL 用法总结

1.ROW_NUMBER()基本用法: SELECT SalesOrderID, CustomerID, ROW_NUMBER() OVER (ORDER BY SalesOrderID) AS RowNumber FROM Sales.SalesOrderHeader 结果集: SalesOrderID CustomerID RowNumber -------------

BlueCode的专栏 1127

Windows 11 上 WSL2 安装 Ubuntu 22.04 保姆级教程(含桌面环境配置)

本文提供在Windows 11上通过WSL2安装Ubuntu 22.04并配置桌面环境的详细教程。涵盖WSL2核心安装、性能调优、Xfce桌面环境部署以及开发环境集成,帮助开发者构建高效、无缝的Windows-Linux混合开发工作站。

Jerry的专栏 633

一起玩儿物联网人工智能小车(ESP32)——48. 利用循迹模块实现循迹小车(三)

摘要:本文介绍循迹小车的接线方法及类的基础知识

一起玩儿科技 1134

SQL SERVER 利用ROW_NUMBER 删除重复数据

        分享一个小知识点,论坛里也常有人问这种问题,表中数据除了ID不同,其他数据一样,然后保存ID最大(或者最小)值,测试数据:--测试数据 if not object_id(N'Tempdb..#T') is null drop table #T Go Create table #T([ID] int,[Name] nvarchar(22),[Class] int) Insert #...

二月十六的博客 1万+

从BIOS到路由器:深入拆解SPI NOR Flash的硬件连接与‘芯片内执行’(XIP)奥秘

本文深入解析SPI NOR Flash的硬件连接与‘芯片内执行’(XIP)技术,从BIOS到路由器的应用场景出发,详细介绍了其架构精髓、典型连接方案、时序设计及性能优化方法。通过实际案例和参数对比,帮助开发者掌握NOR Flash在嵌入式系统中的关键作用与设计技巧,提升电路设计效率与可靠性。

weixin_30522183的博客 491

在MySQL中实现Rank高级排名函数

在MySQL中实现Rank高级排名函数前言用例表1.在MySQL中实现普通排名2.在MySQL中实现并列连续序号排名3.在MySQL中实现并列非连续序号排名 前言 MySQL中没有Rank排名函数,当我们需要查询排名时,只能使用MySQL数据库中的基本查询语句来查询排名,下面有3种具体的实现。(ps:非特殊情况,实际开发尽量使用Redis的sortset去实现排行。) 用例表 接下来的排行实现都采用这个表的数据举例。(ps:建议直接跳过,只是方便测试而已。) SET NAMES utf8mb4; SET F

lj_heaven的博客 4494

【AI之路】cmd命令行通过Huggingface镜像站快速下载模型文件的方法

Hugging Face Hub 是分享机器学习模型、演示、数据集和指标的首选之地。huggingface_hub 库可以轻松下载Huggingface上有用的模型和数据集元数据。但大模型文件通常较大,国内下载太慢,那有没有高效便捷的方法?这个当然必须有!看到了吗?只是添加一个参数,下载大模型就搞定了。当然也可以使用python程序来下载。具体见前期博文:【AI之路】使用huggingface_hub通过huggingface镜像站hf-mirror.com下载大模型(附代码,实现大模型自由)

IT里的交易员-博客 1853

如何理解下一代ERP 即:华为MetaERP

如何理解下一代ERP 即:华为MetaERP 华为的 MetaERP核心定位: 华为MetaERP是华为公司自主研发的下一代企业核心商业管理系统。它不仅仅是一个传统的ERP(企业资源规划)系统,更是一个面向未来、基于云原生、AI驱动、安全可信的企业核心管理平台。

金牌架构师 1142

MySQL中RANK()的介绍和用法

通过RANK()函数,我们可以方便地为查询结果进行排序并为每个行分配排名。这对于学生成绩排行榜、竞赛得分等需要排序和排名的场景非常有用。本文介绍了RANK()函数的概念和使用方法,并通过示例和输出结果向读者展示了具体的操作步骤和效果。

小羊的博客 6669

Nvidia Orin Driveos Camera 介绍及调试详解

自动驾驶-nvidia orin driveos Camera 驱动详解及调试

u011803281的博客 2991

mysql 7 中实现 row_number /rank/dense_rank

关于row_number/rank/dense_rank之间的区别 https://blog.youkuaiyun.com/nayi_224/article/details/79862283 mysql版本5.7.23-log create table test_190507(part VARCHAR(50), val1 NUMERIC, val2 NUMERIC); insert into test_19...

nayi_224的博客 1066

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

mysql实现dense_rank_MySQL 下 ROW_NUMBER / DENSE_RANK / RANK 的实现

CREATE TABLE test_rownum (ID int,Ke CHAR(1),val INT);INSERT INTO test_rownumSELECT 1, 'A', 1 UNION ALLSELECT 2, 'A', 2 UNION ALLSELECT 3, 'A', 3 UNION ALLSELECT 4, 'B', 1 UNION ALLSELECT 5, 'B', 2 UN...

weixin_39692037的博客 230

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

dense rank改为mysql_[转载]MySQL 下 ROW_NUMBER / DENSE_RANK / RANK 的实现

CREATE TABLE test_rownum (ID int,Ke CHAR(1),val INT);INSERT INTO test_rownumSELECT 1, 'A', 1 UNION ALLSELECT 2, 'A', 2 UNION ALLSELECT 3, 'A', 3 UNION ALLSELECT 4, 'B', 1 UNION ALLSELECT 5, 'B', 2 UNI...

weixin_32409707的博客 129

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

ok-ww 鸣潮挂机教程:3 步跑完日常与刷图指南

ok-ww 是《鸣潮》的后台自动战斗工具。登录、领卡、刷体力、清声骸,这些 ok-ww 一键日常能串起来的事,它全包了。全程只模拟键鼠,不读游戏内存。每天被固定流程拴住半小时的玩家,就是它要服务的人。 ## 30 秒看懂它怎么跑 把它想成一个只配了摄像头的替班同事。他坐在你电脑前盯着游戏画面,手里能动的只有你的键盘鼠标。游戏进程里的数据,他一个字节都摸不到。界面改版了,他得换一批识别模板;服务

gitblog_01035的博客 140

mysql怎么做价格排序_MySQL中如何对数据进行排序

文章目录image.png在MYSQL的最新版本MYSQL8已经支持了排名函数RANK,DENSE_RANK和ROW_NUMBER。但是在就得版本中还不支持这些函数,只能自己实现。实现方法主要用到了条件判断语句(CASE WHEN或IF)和添加临时变量。1. 排名分类1.1 区别RANK,DENSE_RANK和ROW_NUMBERRANK并列跳跃排名,并列即相同的值,相同的值保留重复名次,遇到下一...

weixin_33837516的博客 745

低版本mysql 实现row_number() ,rank() ,dense_rank()及其窗口函数

测试表 create table test (id int(4) , name VARCHAR(10) ) row_number() 实现 SELECT t.name , t.id, (@cur_rank := @cur_rank + 1) ranking FROM test t , (SELECT @cur_rank := 0) r ORDER BY id DESC; ROW_NUMBER() over(partiton by name ORDER BY id DESC) 实现

A_single_cat的博客 2236

MySQL 8.0窗口函数实战:如何用rank()、dense_rank()和row_number()解决学生成绩排名问题

本文通过学生成绩排名的实战案例,详细解析了MySQL 8.0中窗口函数的使用,重点对比了rank()、dense_rank()和row_number()三个核心排名函数在处理并列、跳号及生成唯一序号时的差异与应用场景。文章旨在帮助读者掌握如何利用窗口函数高效、优雅地解决复杂的数据排序与分析问题,提升SQL查询能力。

butter的博客 445

MySQL部门薪资Top3:7种写法与RANK、DENSE_RANK全解析

在数据处理与后端开发中,按分组取TopN是高频需求,而SQL的排名逻辑常因并列处理方式不同产生迥异结果。MySQL 8.0引入窗口函数后,DENSE_RANK、RANK与ROW_NUMBER为这类查询提供了简洁高效的解法,可精准实现部门薪资前三等统计。对于仍使用MySQL 5.7的存量系统,相关子查询与自连接也是可靠替代,但其性能依赖索引设计与连接方式。理解不同排名语义、版本差异与索引优化,不仅能让SQL通过面试考验,也能在实际报表与绩效分析中避免返工。以同一份员工数据,拆解七种可运行写法及适用边界。

weixin_30983353的博客 285

MySQL窗口函数实战排名、分区与累计计算的进阶技巧

窗口函数的核心在于OVER()子句,它定义了函数计算的窗口范围。常见的窗口函数包括ROW_NUMBER(), RANK(), DENSE_RANK(), SUM(), AVG()等。我们还可以定义更灵活的窗口帧,例如计算最近3行的移动平均:`AVG(amount) OVER (PARTITION BY salesperson ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)`。而DENSE_RANK()则不会跳号(如1,2,2,3)。

SenJune的博客 744

MySQL窗口函数实战:从排名到趋势分析的完整指南

本文深入探讨MySQL窗口函数的实战应用,从基础排名到复杂趋势分析,提供完整指南。通过电商排名、销售累计计算等真实案例,展示窗口函数如何高效解决传统SQL痛点,提升查询性能和开发效率。特别分享性能优化的黄金法则,帮助开发者避免常见陷阱。

weixin_29224529的博客 370

SQL 必知必会:手把手教你掌握 MySQL 开窗函数的 4 大核心场景(附代码)

想象你站在一个长长的队伍里(这就是你的数据表)。普通聚合:老师让全班同学抱成一团,只告诉你全班的平均分。你失去了自我,变成了一个数字。开窗函数:老师给你戴上了一副“智能眼镜”。你还是站在队伍里(行数不变)。但你的眼镜上显示了各种信息:全班的平均分、你在班里的排名、你前一个人的分数……这就是开窗函数的核心:不改变行数,但能进行跨行计算。当你发现你需要“既要...又要...”既要保留明细数据,又要看聚合统计(如:显示每个订单,同时显示该用户的总消费额)。> 用既要看当前行,又要。

2301_76481487的博客 321

MySQL开窗函数

开窗函数是mysql8.0中的新特性,用于实现和group by分组函数类似的分组聚合功能。分组函数:对一个集合输出一个标量结果,改变了数据的粒度,且丢失了非分组字段及非聚合字段的信息。开窗函数:分别以每一行为当前行,与当前行相关的所有行为窗口,对同一个窗口内的数据进行聚合等类似操作,结果附加到当前行的后面,不改变原始数据粒度,不丢失原始数据信息。这部分可以直接查看文档,个人觉得这部分算是开窗函数里最重要的了,弄明白了各种情况下窗口的大小,其他的就没啥容易混淆的点了。rows和range。

atwdy的博客 6201

LeetCode 184 题解:部门工资最高的员工——等值连接 + 子查询与窗口函数 RANK 的实战对比

本文基于 doocs/leetcode 仓库中 [184. Department Highest Salary](https://link.gitcode.com/i/e27ddfa9fed31ef6e9a729ed00874e27) 的官方题解,完整解析「查找每个部门中薪资最高的员工(并列需全部保留)」这一经典数据库面试题。你将掌握两套可直接运行的解法——「等值连接 + 子查询」与「等值连接 +

gitblog_01062的博客 221
上一篇: python sklearn 分类算法简单调用
下一篇: 机器学习-损失函数
Bryan__
博客等级 码龄12年 2500粉丝 166原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值