【硬刚Hive】Hive窗口函数row number的用法

article/2025/9/19 6:47:49

row_number

前面我们介绍窗口函数的时候说到了窗口函数的使用场景,我们也给它起了一个名字进行区分,通用窗口函数和特殊窗口函数,今天我们就来看一下排序相关的窗口函数,因为是窗口函数,并且我们说它是用来排序的,我们大概也能猜到它就是用来对窗口内的数据进行排序的

其实关于排序我们前面也介绍过order by,sort by 等排序的方式Hive语法之常见排序方式,为什么还有窗口函数进行排序的,因为前面的order by,sort by 等虽然可以排序但是不能给我们返回排序的值(名次),如果你用过mysql 的话,这个时候你就知道写存储过程或者使用自定义变量来完成这个功能,row number 也是一样的道理,可以按照我们自定义的排序规则,返回对应的排序先后顺序的值

所以我们认为row_number是窗口排序函数,但是hive 也没有提供非窗口的排序函数,但是我们前面说过了如果没有窗口的定义中没有partition by 那就是将整个数据输入当成一个窗口,那么这种情况下我们也可以使用窗口排序函数完成全局排序。

测试数据

下面有一份测试数据id,dept,salary,然后我们就使用这份测试数据学习我们的窗口排序函数

1,销售,10000
2,销售,14000
3,销售,10000
4,后端,20000
5,后端,25000
6,后端,32000
7,AI,40000
8,AI,35000
9,AI,60000
10,数仓,20000
11,数仓,30000
12,数仓,32000
13,数仓,42000
create table ods_num_window(id string,dept string,salary int
) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
LOAD DATA LOCAL INPATH '/Users/liuwenqiang/workspace/hive/number.txt' OVERWRITE INTO TABLE ods_num_window;

从例子中学习 row_number

每个部门的员工按照工资降序排序

select*,row_number() over(partition by dept order by salary desc) as rn
fromods_num_window
;

file

我们看到每个部门都有自己的第一名,明显的可以看到排序是发生在每个部门内部的

全部的员工按照工资降序排序

select*,row_number() over(order by salary desc) as rn
fromods_num_window
;

file

当我们没有定义partition by 子句的时候,我们的所有数据都放在一个窗口里面,这个时候我们的排序就是全局排序,其实如果你仔细看过我们的Hive语法之窗口函数初识这一节的话,你就知道partition by 其实是定义了子窗口,如果没有子窗口的话,那就就是一个窗口,如果所有的数据都放在一个窗口的话那就是全局排序

取每个部门的工资前两名

这个是row_number() 函数非常常见的使用场景top-N,其实如果你仔细看过我们的Hive语法之窗口函数初识这一节的话,你就知道partition by 其实是定义了子窗口,那其实这里的top-N,本质上是子窗口的的top-N

select*
from(select*,row_number() over(partition by dept order by salary desc) as rnfromods_num_window
) tmp
wherern <=2
;

file

其实这个的实现方式就是我们对数据在子窗口内进行排序,然后选择出我们我们需要的数据,也就是这里的rn <=2

rank 和 dense_rank

其实这两个窗口函数和row_number 是一样的,都是窗口排序函数,既然这样那为什么还有这两个函数呢,存在即合理,我们看一下row_number 函数,这次我们采用升序排序

    *,row_number() over(partition by dept order by salary) as rn
fromods_num_window
;

我们看到在销售部门有两个人的工资其实是一样的10000,但是排名不一样

file

接下来我们看一下rank,我们发现销售部门那两个工资相等的实并列第一了,然后下一个人直接第三了

file

接下来我们再看一下 dense_rank,工资相等的两个人依然是排名相等的,但是下一个人还是第二

file

使用场景

Top-N

Top-n 前面我们已经介绍过了,这里就不再介绍了

计算连续

什么是计算连续呢,这个名字有点不太合理,这里举个例子方便大家理解,加入我有个用户访问日志表,那我想筛选出哪些超过连续7天都访问的用户,或者我想计算连续访问天数最大的10位用户

下面是一份测试数据用户ID,访问日期

1,2020-12-01
1,2020-12-02
1,2020-12-03
1,2020-12-04
1,2020-12-05
1,2020-12-06
1,2020-12-07
1,2020-12-08
1,2020-12-09
1,2020-12-10
2,2020-12-01
2,2020-12-02
2,2020-12-03
2,2020-12-04
2,2020-12-06
2,2020-12-07
2,2020-12-08

下面是我们的建表语句

CREATE TABLE ods.ods_user_log (id string,ctime string
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;
load data local inpath '/Users/liuwenqiang/workspace/hive/user_log.txt' overwrite into table ods.ods_user_log;

现在我们分析一下这个问题,怎么计算连续呢,计算肯定是针对同一个用户的,然后我们可以按照用户的访问时间进行排序,然后我们用日期的数字减去对应的排序就会得到一个值,如果访问时间是连续的话,我们就可以得到同一个值

selectid,ctime,row_number(partition by id order by ctime ) as rn
fromods_user_log
;

file

这里为了演示效果比较明显,所以设计的数据有点特殊,大家可以看到对于id 是1的用户,我们发现从12月1号到12月10号,我们的排名也依次是从1到10的,这个时候我们只要将日期变成对于的数字,然后减去对应的排名它是等于20201200的,这个时候我们只需要统计20201200的个数,这个个数就是连续登陆的天数,这里我们就不把日期转换成转换成数字然后做减法了,我们直接使用日期去减。

selectid,ctime,date_sub(cast(ctime as date),row_number() over(partition by id order by ctime)),row_number() over(partition by id order by ctime ) as rn
fromods_user_log
;

file

这下我再去统计每个用户的相同日期有多少个即可,在我这里因为是7天,所以我只需要计算出相同日期的个数大于等于7即可

selectid,kt,count(1) as loginCnt
from (selectid,ctime,date_sub(cast(ctime as date),row_number() over(partition by id order by ctime)) as kt,row_number() over(partition by id order by ctime ) as rnfromods_user_log
) tmp
group byid,kt
havingcount(1)>=7
;

file

我们尝试着理解一下这个数据,它的意思就是用户1 从(2020-11-30+1) 日开始,连续10天访问了网站

这里有个问题需要注意一下,那就是上面我造的数据就是每天一条的,如果每天如果有多条,那我们上面的代码就不对了,所以这个时候我们不是需要使用dense_rank,大家注意理解一下,我们需要的是去重,大家注意理解一下

分组抽样

其实抽样这个东西大家都接触过,随机抽样也接触过,今天我们学习一下分组随机抽样,其实实现很简单,我们使用row_number 在子窗口内随机排序,然后抽出所需的样本数据即可,我们还是用上面的数据,每个用户随机抽取三天登陆

select*
from (selectid,ctime,row_number() over(partition by id order by rand() ) as rnfromods_user_log
) tmp
where rn<=3
;

file

总结

  • rank() 排序相同时会重复,总数不会变(会有间隙跳跃,数据不连续)
  • dense_rank() 排序相同时会重复,总数会减少(不会有间隙,数据连续的)
  • row_number() 会根据顺序计算,不会重复不会减少
  • Row_number 函数常用的三种场景Top-N,计算连续,分组抽样

http://chatgpt.dhexx.cn/article/UOC10pkZ.shtml

相关文章

使用ROW_NUMBER()查询:列名 'RowNumber' 无效。(转载)

原文地址&#xff1a;https://my.oschina.net/wangzan/blog/202456 使用ROW_NUMBER()方法查询结果集&#xff1b;语句如下&#xff1a; select ROW_NUMBER() OVER(ORDER BY dbo.OrderOutProduct.ID) AS RowNumber,dbo.Order.ID,Telephone,AddressCity,Province, from dbo.Order…

SQL | 窗口函数 row number + partition by 排序

窗口函数 row number partition by 排序 1 背景2 SQL牛逼函数走起来2.1 Step12.2 SQL实现12.3 Step23.4 SQL实现22.5 补充-collect函数 3 头条面试SQL题3.1 题目3.2 实现3.2 建表 1 背景 今天实习学到了一个很牛逼的sql函数&#xff0c;而且解决了一个之前面试头条时候的SQL问…

pandas 实现sql row number 功能

1. pandas 实现sql row number 功能 先按照id和msg_ts排序&#xff0c; 然后按照id topic分组&#xff0c;row number功能就现实了 df[row_num] df.sort_values([id, msg_ts], ascendingTrue).groupby([id, topic]).cumcount() 1 padans链接&#xff1a; https://pandas.…

ROW_NUMBER 用法小结

ROW_NUMBER函数是返回结果集分区内行的序列号&#xff0c;每个分区的第一行从 1 开始。 CREATE TABLE [dbo].[tb_Seller]([编号] [nvarchar](50) NULL,[商品名称] [nvarchar](50) NULL,[销售额] [money] NULL,[利润] [money] NULL,[门店名称] [nvarchar](50) NULL,[日期] [sma…

ROW_NUMBER() OVER()函数用法详解 (分组排序 例子多)

语法格式&#xff1a;row_number() over(partition by 分组列 order by 排序列 desc) row_number() over()分组排序功能&#xff1a; 在使用 row_number() over()函数时候&#xff0c;over()里头的分组以及排序的执行晚于 where 、group by、 order by 的执行。 例一&#…

Row_number()函数用法

Row_number()函数是SQL SERVER系统函数中的一种&#xff0c;它为结果集的分区中的每一行分配一个连续的整数。简单的说就是生成一个独表&#xff0c;序号以每个分区的第一行开头&#xff0c;下面是其基本语法&#xff1a; PARTITION BY子句将结果集划分为分区。 ROW_NUMBER()…

SQL Server中row_number函数用法介绍

一、SQL Server Row_number函数简介 ROW_NUMBER()是一个Window函数&#xff0c;它为结果集的分区中的每一行分配一个连续的整数。 行号以每个分区中第一行的行号开头。 语法实例&#xff1a; select *&#xff0c;row_number() over(partition by column1 order by column2)…

SQL中row_number函数用法

row_number函数用法 1、函数讲解2、LeetCode实战 1、函数讲解 语法&#xff1a;ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN)简单的说&#xff0c;row_number()从1开始&#xff0c;为每条分组记录返回一个数字&#xff0c;举例&#xff1a; ROW_NUMBER() OVER(OR…

如何查看Vue项目vue的版本号

如果是用vue-cli创建的项目&#xff0c;则找到项目根目录下的"package.json"文件 如果是要查看vue-cli的版本号的话&#xff0c;则键盘WinR&#xff0c;输入cmd&#xff0c;再在cmd里面输入vue -V

查看vue版本号

查看npm安装包的版本号&#xff0c;一般情况是都是执行&#xff1a; 包名 --version 或 包名 -V。 当执行vue --version时&#xff0c;如果安装了vue/cli 那么得到的是vue/cli的版本&#xff0c;而不是vue的。 所以正确查看方式是执行&#xff1a; npm list vue如图所示&…

uni-app中查看vue的版本号

1.查看vue的版本号 在manifest.json 文件中&#xff0c;基础配置的底部有vue版本的配置

如何查看vue版本号以及vue/cli脚手架版本号

查看vue版本号 方法一&#xff1a;直接在项目的package.json文件&#xff0c;找到dependencies就能看到了 方法二&#xff1a;输入命令npm ls vue (或者npm list vue) 查看vue/cli脚手架版本号 方法&#xff1a;输入命令vue -V (或者vue --version&#xff09;

vue cli更换版本

vue-cli更换版本 vue更换版本 最近要写个小项目&#xff0c;用到了vue&#xff0c;于是安装了vue cli&#xff0c;但是在使用过程中发现最新的版本好像不太好用&#xff0c;想换成旧版本。 查看当前版本 通过vue -V可以查看当前版本&#xff0c;现有版本是5.0.8&#xff0c…

查看vue版本,cli版本,npm以及node版本

1.查看vue版本 package.json 文件中2.查看vue-cli版本 命令&#xff1a; vue -V3.查看npm版本 命令&#xff1a; npm -v4.查看node版本 命令&#xff1a; node -v5.自测版本号截图

查看vue版本号、vue-cli版本号

查看vue版本号 方法一&#xff1a;npm ls vue方法二&#xff1a;package.json查看vue-cli版本号 vue -V两者不要搞混哦

vue -V查看vue版本时,提示vue.js缺少标识符

vue -V查看vue版本时&#xff0c;提示vue.js缺少标识符 出现的错误提示如下图。 我的解决办法&#xff1a; winR打开 cmd 输入 where vue。 找到D:\a_tools\vue,删除该文件夹中的vue.js。 重新输入vue -V 查看版本号。

查看vue版本和vue脚手架版本

打开cmd控制台&#xff1a; 输入vue --version&#xff08;俩个-&#xff09;或 vue -V&#xff08;第二个V要大写&#xff09;查看vue脚手架版本&#xff1b; 输入npm list vue -g 查看vue版本和vue脚手架版本&#xff1b;

如何查看vue版本号

如何查看vue版本号 先来看一个错误示范 在cmd控制台内&#xff0c;输入npm -v 可查看到npm 的版本号&#xff1b; vue -V 可看到vue的版本号。 这个是vue脚手架的版本号。 来看正确的方式 npm list vue在控制台输入上述3个单词

查看vue的版本命令,以及vue脚手架的版本命令

查看vue版本的命令&#xff1a; 【 害我找了半天&#xff01;&#xff01;&#xff01; 谁不知道-version啊&#xff0c;一天天净发些没用的 】 npm list vue 脚手架版本命令&#xff0c;这个大家倒是都知道 vue -V 或者 vue --version 升级vue至最新版本&#xff1a; 【vue3.…

如何查看 当前安装的vue版本

目录 1 实现 1 实现 要查看当前安装的 Vue 版本&#xff0c;可以使用以下方法&#xff1a; 在终端或命令提示符中运行以下命令&#xff1a; vue --version如果你使用的是 Vue CLI 创建的项目&#xff0c;可以在项目的根目录中找到 package.json 文件。在该文件中&#xff0c…