MySQL中的ROW_NUMBER窗口函数简单了解下
ROW_NUMBER() 是 MySQL8引入的窗口函数之一,它为查询结果集中的每一行分配一个唯一的顺序号(行号)。这个顺序号是基于窗口函数的 ORDER BY 子句进行排序的,可以根据指定的排序顺序生成连续的整数值。
ROW_NUMBER() 在分页、去重、分组内排序等场景中非常有用。
本文涉及到的脚本测试请在个人测试库进行。
使用场景
- **分页查询:**使用
ROW_NUMBER()可以生成每行的序号,结合WHERE或LIMIT子句实现高效的分页查询。尤其是在没有OFFSET支持的情况下,ROW_NUMBER()允许你在分页时进行灵活的排序。 - **去除重复数据:**可以利用
ROW_NUMBER()来给每一行打上唯一标识,之后选择每组的第一行,从而有效地去除重复数据。 - **分组内排序:**可以按组对数据进行排序,并为每个组中的行分配一个行号。这个场景通常用于比如给每个订单中的商品按价格排序,并为每个订单挑选排名第一的商品。
- **数据排名:**使用
ROW_NUMBER()可以为查询结果中的数据进行排名,适用于例如学生成绩排名、销售业绩排名等场景。
语法
ROW_NUMBER() OVER (PARTITION BY partition_expression ORDER BY order_expression) AS row_num
PARTITION BY:可选,按指定字段分组。相同分组内的行号会重新从 1 开始。ORDER BY:指定排序字段,行号的生成顺序由此决定。
示例
假设有一个电商数据库,包含 orders 和 order_items 表,使用 ROW_NUMBER() 来展示几种常见场景。
示例 1:为每个订单中的商品按价格排名
可以为每个订单中的商品按价格进行排序,并为每个商品分配一个排名。
-- 创建 orders 表
CREATE TABLE orders (order_id INT AUTO_INCREMENT PRIMARY KEY,customer_name VARCHAR(100),order_date DATE
);-- 创建 order_items 表
CREATE TABLE order_items (order_item_id INT AUTO_INCREMENT PRIMARY KEY,order_id INT,product_name VARCHAR(100),quantity INT,unit_price DECIMAL(10, 2),FOREIGN KEY (order_id) REFERENCES orders(order_id)
);-- 插入数据
INSERT INTO orders (customer_name, order_date) VALUES
('Alice', '2024-10-01'),
('Bob', '2024-10-02'),
('Charlie', '2024-10-03');INSERT INTO order_items (order_id, product_name, quantity, unit_price) VALUES
(1, 'Laptop', 1, 1000.00),
(1, 'Phone', 2, 500.00),
(1, 'Tablet', 1, 300.00),
(2, 'Headphones', 2, 100.00),
(2, 'Mouse', 1, 50.00),
(3, 'Smartwatch', 1, 150.00),
(3, 'Laptop', 1, 800.00);
查询:为每个订单中的商品按 unit_price 排序,给出排名
SELECT oi.order_id, oi.product_name, oi.unit_price,ROW_NUMBER() OVER (PARTITION BY oi.order_id ORDER BY oi.unit_price DESC) AS `rank`
FROM order_items oi;
结果
| order_id | product_name | unit_price | rank |
|---|---|---|---|
| 1 | Laptop | 1000.00 | 1 |
| 1 | Phone | 500.00 | 2 |
| 1 | Tablet | 300.00 | 3 |
| 2 | Headphones | 100.00 | 1 |
| 2 | Mouse | 50.00 | 2 |
| 3 | Laptop | 800.00 | 1 |
| 3 | Smartwatch | 150.00 | 2 |
在这个例子中,使用 ROW_NUMBER() 按照每个 order_id 对商品按 unit_price 从高到低排序,并为每个商品分配了一个行号(排名)。
如果只想获取每个订单中价格最高的商品,可以在查询外层再加一个 WHERE rank = 1 来筛选。
示例 2:去除重复数据
假设 order_items 表中有重复的记录,可以利用 ROW_NUMBER() 给每一行编号,然后只保留每组中第一个出现的记录(行号为 1)。
插入重复数据
INSERT INTO order_items (order_id, product_name, quantity, unit_price) VALUES
(1, 'Laptop', 1, 1000.00), -- 重复记录
(2, 'Mouse', 1, 50.00), -- 重复记录
(3, 'Smartwatch', 1, 150.00);
查询:去除重复记录
WITH ranked_items AS (SELECT oi.order_item_id, oi.order_id, oi.product_name, oi.unit_price,ROW_NUMBER() OVER (PARTITION BY oi.order_id, oi.product_name ORDER BY oi.order_item_id) AS rnFROM order_items oi
)
SELECT order_item_id, order_id, product_name, unit_price
FROM ranked_items
WHERE rn = 1;
| order_item_id | order_id | product_name | unit_price |
|---|---|---|---|
| 1 | 1 | Laptop | 1000.00 |
| 2 | 1 | Phone | 500.00 |
| 3 | 1 | Tablet | 300.00 |
| 4 | 2 | Headphones | 100.00 |
| 5 | 2 | Mouse | 50.00 |
| 7 | 3 | Laptop | 800.00 |
| 6 | 3 | Smartwatch | 150.00 |
在这个查询中,ROW_NUMBER() 根据 order_id 和 product_name 为每一组商品打上编号,PARTITION BY 确保每个订单中同一个商品只保留一次。WHERE rn = 1 确保每个分组只保留第一条记录,从而去除了重复的商品条目。
示例 3:分页查询
假设需要分页展示订单项,每页展示 2 条数据。可以使用 ROW_NUMBER() 来为查询结果生成行号,并结合 WHERE 子句限制显示特定页的数据。
查询:分页显示第二页数据(每页显示 2 条)
WITH ranked_items AS (SELECT oi.order_item_id, oi.order_id, oi.product_name, oi.unit_price,ROW_NUMBER() OVER (ORDER BY oi.order_item_id) AS rnFROM order_items oi
)
SELECT order_item_id, order_id, product_name, unit_price
FROM ranked_items
WHERE rn BETWEEN 3 AND 4;
结果
| order_item_id | order_id | product_name | unit_price |
|---|---|---|---|
| 3 | 1 | Tablet | 300.00 |
| 4 | 2 | Headphones | 100.00 |
在这个分页查询中,ROW_NUMBER() 为查询结果集中的每一行分配了一个行号,然后通过 WHERE rn BETWEEN 3 AND 4 获取第 2 页的结果(假设每页 2 条数据)。
总结
ROW_NUMBER() 在 MySQL 中是一个强大的窗口函数,具有以下几个主要用途:
- 分页查询:通过生成行号来实现高效分页。
- 去重:利用分组和行号,可以去除重复数据。
- 分组排序:对每个分组内的数据进行排序并生成排名。
- 数据排名:计算排名或为数据按某种规则分配顺序。
MySQL 8.0 引入的窗口函数使得许多复杂的查询变得更加简洁和高效,特别是在处理排名、去重和分页等场景时。
关于作者
来自全栈程序员nine的探索与实践,持续迭代中。(技术交流codetrend)
相关文章:
MySQL中的ROW_NUMBER窗口函数简单了解下
ROW_NUMBER() 是 MySQL8引入的窗口函数之一,它为查询结果集中的每一行分配一个唯一的顺序号(行号)。这个顺序号是基于窗口函数的 ORDER BY 子句进行排序的,可以根据指定的排序顺序生成连续的整数值。 ROW_NUMBER() 在分页、去重、…...
day24|leetCode 93.复原IP地址 , 78.子集 , 90.子集II
8.复原ip地址 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 . 分隔。 例如:"0.1.2.201" 和"192.168.1.1" 是 有效 IP 地址,但是 "…...
RocketMQ: Broker 使用指南
Broker 配置参数 获取 Broker 的默认配置 $ sh mqbroker -m Broker 启劢时,如何加载配置 ### 第一步生成 Broker 默认配置模版 sh mqbroker -m > broker.p ### 第二步修改配置文件, broker.p ### 第三步加载修改过的配置文件 nohup sh mqbroker -c broker.pBrok…...
【Linux 篇】Docker 的容器之海与镜像之岛:于 Linux 系统内探索容器化的奇妙航行
文章目录: 【Linux 篇】Docker 的容器之海与镜像之岛:于 Linux 系统内探索容器化的奇妙航行前言安装docker-centos7 【Linux 篇】Docker 的容器之海与镜像之岛:于 Linux 系统内探索容器化的奇妙航行 💬欢迎交流:在学习…...
5、AI测试辅助-生成测试用例思维导图
AI测试辅助-生成测试用例思维导图 创建测试用例两种方式1、Plantuml思维导图版本 (不推荐)2、Markdown思维导图版本(推荐) 创建测试用例两种方式 完整的测试用例通常需要包含以下的元素: 1、测试模块 2、测试标题 3、前置条件 4、…...
nature communications论文 解读
题目《Transfer learning with graph neural networks for improved molecular property prediction in the multi-fidelity setting》 这篇文章主要讨论了如何在多保真数据环境(multi-fidelity setting)下,利用图神经网络(GNNs&…...
基于Java Springboot公园管理系统
一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA/eclipse 数据…...
神经网络(系统性学习三):多层感知机(MLP)
相关文章: 神经网络中常用的激活函数 神经网络(系统性学习一):入门篇 神经网络(系统性学习二):单层神经网络(感知机) 多层感知机(MLP) 多层感…...
07-SpringCloud-Gateway新一代网关
一、概述 1、Gateway介绍 官网:https://spring.io/projects/spring-cloud-gateway Spring Cloud Gateway组件的核心是一系列的过滤器,通过这些过滤器可以将客户端发送的请求转发(路由)到对应的微服务。 Spring Cloud Gateway是加在整个微服务最前沿的防…...
HTML 表单实战:从创建到验证
HTML表单是用于收集用户输入数据的一种方式,可以用于创建各种类型的表单,例如登录表单、注册表单、调查问卷表单等。本文将详细介绍表单元素的使用,并利用JavaScript实现对表单数据的验证。 HTML表单元素的使用 输入框<input> <i…...
【redis 】string类型详解
string类型详解 一、string类型的概念二、string类型的常用指令2.1 SET2.2 GET2.3 MSET2.4 MGET2.5 SETNX2.6 INCR2.7 INCRBY2.8 DECR2.9 DECRBY2.10 INCRBYFLOAT2.11 APPEND2.12 GETRANGE2.13 SETRANGE2.14 STRLEN 三、string类型的命令小结四、string类型的内部编码五、strin…...
Vue.js 学习总结(13)—— Vue3 version 计数介绍
前言 Vue3.5 提出了两个重要概念:version计数和双向链表,作为在内存和计算方面性能提升的最大功臣。既然都重要,那就单挑 version 计数来介绍,它在依赖追踪过程中,起到快速判断依赖项有没有更新的作用,所以…...
【数据结构】【线性表】一文讲完队列(附C语言源码)
队列 队列的基本概念基本术语基本操作 队列的顺序实现顺序队列结构体的创建顺序队列的初始化顺序队列入队顺序队列出队顺序队列存在的问题分析循环队列代码汇总 队列的链式实现链式队列的创建链式队列初始化-不带头结点链式队列入队-不带头节点链式队列出队-不带头结点带头结点…...
2024年11月最新 Alfred 5 Powerpack (MACOS)下载
在现代数字化办公中,我们常常被繁杂的任务所包围,而时间的高效利用成为一项核心需求。Alfred 5 Powerpack 是一款专为 macOS 用户打造的高效工作流工具,以其强大的定制化功能和流畅的用户体验,成为众多效率爱好者的首选。 点击链…...
ODBC连接PostgreSQL数据库后,网卡DOWN后,客户端进程阻塞问题解决方法
问题现象:数据库客户端进程数据库连接成功后,再把跟数据库交互的网卡down掉,客户端进程就会阻塞,无法进行其他处理。该问题跟TCP keepalive机制有关。 可以在odbc.ini文件中增加相应的属性来解决,在odbc.ini 增加如下…...
VsCode使用git提交很慢(一直显示在提交)_vscode commit很慢解决方法
VsCode使用git提交很慢(一直显示在提交)_vscode commit很慢...
linux从0到1——shell编程9
声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&a…...
计算机网络技术专业,热门就业方向和就业前景
前言 在数字化飞速发展的今天,计算机网络技术专业成为了众多学子和职场人士关注的焦点。这一专业不仅涵盖了计算机硬件、软件和网络通信等多个领域的知识,更在就业市场上展现出强大的竞争力。本文将带您一探计算机网络技术专业的就业方向和就业前景&…...
C++中定义类型名的方法
什么是 C 中的类型别名和 using 声明? 类型别名与using都是为了提高代码的可读性。 有两种方法可以定义类型别名 一种是使用关键字typedef起别名使用别名声明来定义类型的别名,即使用using. typedef 关键字typedef作为声明语句中的基本数据类型的一…...
从零开始学习 sg200x 多核开发之 camera-sensor 添加与测试
sg2002 集成了 H.264 视频压缩编解码器, H.265 视频压缩编码器和 ISP;支持 HDR 宽动态、3D 降噪、除雾、镜头畸变校正等多种图像增强和矫正算法。 sophpi 中没有提供相关图像 sensor。本次实验是在 milkv-duo256m 上添加 GC2083。 GC2083 格科微的 GC2083 是一款…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...
yaml读取写入常见错误 (‘cannot represent an object‘, 117)
错误一:yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因,后面把yaml.safe_dump直接替换成yaml.dump,确实能保存,但出现乱码: 放弃yaml.dump,又切…...
