自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Hive窗口函數(shù)Row Number的用法, 你肯定都會吧!

大數(shù)據(jù)
前面我們介紹窗口函數(shù)的時候說到了窗口函數(shù)的使用場景,我們也給它起了一個名字進行區(qū)分,通用窗口函數(shù)和特殊窗口函數(shù),今天我們就來看一下排序相關(guān)的窗口函數(shù),因為是窗口函數(shù),并且我們說它是用來排序的,我們大概也能猜到它就是用來對窗口內(nèi)的數(shù)據(jù)進行排序的。

[[374553]]

本文轉(zhuǎn)載自微信公眾號「Java大數(shù)據(jù)與數(shù)據(jù)倉庫」,作者劉不二 。轉(zhuǎn)載本文請聯(lián)系Java大數(shù)據(jù)與數(shù)據(jù)倉庫公眾號。

row_number

前面我們介紹窗口函數(shù)的時候說到了窗口函數(shù)的使用場景,我們也給它起了一個名字進行區(qū)分,通用窗口函數(shù)和特殊窗口函數(shù),今天我們就來看一下排序相關(guān)的窗口函數(shù),因為是窗口函數(shù),并且我們說它是用來排序的,我們大概也能猜到它就是用來對窗口內(nèi)的數(shù)據(jù)進行排序的

其實關(guān)于排序我們前面也介紹過order by,sort by 等排序的方式Hive語法之常見排序方式,為什么還有窗口函數(shù)進行排序的,因為前面的order by,sort by 等雖然可以排序但是不能給我們返回排序的值(名次),如果你用過mysql 的話,這個時候你就知道寫存儲過程或者使用自定義變量來完成這個功能,row number 也是一樣的道理,可以按照我們自定義的排序規(guī)則,返回對應(yīng)的排序先后順序的值

所以我們認(rèn)為row_number是窗口排序函數(shù),但是hive 也沒有提供非窗口的排序函數(shù),但是我們前面說過了如果沒有窗口的定義中沒有partition by 那就是將整個數(shù)據(jù)輸入當(dāng)成一個窗口,那么這種情況下我們也可以使用窗口排序函數(shù)完成全局排序。

測試數(shù)據(jù)

下面有一份測試數(shù)據(jù)id,dept,salary,然后我們就使用這份測試數(shù)據(jù)學(xué)習(xí)我們的窗口排序函數(shù)

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

從例子中學(xué)習(xí) row_number

每個部門的員工按照工資降序排序

  1. select 
  2.     *,row_number() over(partition by dept order by salary descas rn 
  3. from 
  4.     ods_num_window 

 

我們看到每個部門都有自己的第一名,明顯的可以看到排序是發(fā)生在每個部門內(nèi)部的

全部的員工按照工資降序排序

  1. select 
  2.     *,row_number() over(order by salary descas rn 
  3. from 
  4.     ods_num_window 

 

當(dāng)我們沒有定義partition by 子句的時候,我們的所有數(shù)據(jù)都放在一個窗口里面,這個時候我們的排序就是全局排序,其實如果你仔細看過我們的Hive語法之窗口函數(shù)初識這一節(jié)的話,你就知道partition by 其實是定義了子窗口,如果沒有子窗口的話,那就就是一個窗口,如果所有的數(shù)據(jù)都放在一個窗口的話那就是全局排序

取每個部門的工資前兩名

這個是row_number() 函數(shù)非常常見的使用場景top-N,其實如果你仔細看過我們的Hive語法之窗口函數(shù)初識這一節(jié)的話,你就知道partition by 其實是定義了子窗口,那其實這里的top-N,本質(zhì)上是子窗口的的top-N

  1. select 
  2.     * 
  3. from
  4.    select 
  5.        *,row_number() over(partition by dept order by salary descas rn 
  6.    from 
  7.        ods_num_window 
  8. ) tmp 
  9. where 
  10.     rn <=2 

 

其實這個的實現(xiàn)方式就是我們對數(shù)據(jù)在子窗口內(nèi)進行排序,然后選擇出我們我們需要的數(shù)據(jù),也就是這里的rn <=2

rank 和 dense_rank

其實這兩個窗口函數(shù)和row_number 是一樣的,都是窗口排序函數(shù),既然這樣那為什么還有這兩個函數(shù)呢,存在即合理,我們看一下row_number 函數(shù),這次我們采用升序排序

  1. select 
  2.     *,row_number() over(partition by dept order by salary) as rn 
  3. from 
  4.     ods_num_window 

我們看到在銷售部門有兩個人的工資其實是一樣的10000,但是排名不一樣

 

接下來我們看一下rank,我們發(fā)現(xiàn)銷售部門那兩個工資相等的實并列第一了,然后下一個人直接第三了

 

接下來我們再看一下 dense_rank,工資相等的兩個人依然是排名相等的,但是下一個人還是第二

 

使用場景

Top-N

Top-n 前面我們已經(jīng)介紹過了,這里就不再介紹了

計算連續(xù)

什么是計算連續(xù)呢,這個名字有點不太合理,這里舉個例子方便大家理解,加入我有個用戶訪問日志表,那我想篩選出哪些超過連續(xù)7天都訪問的用戶,或者我想計算連續(xù)訪問天數(shù)最大的10位用戶

下面是一份測試數(shù)據(jù)用戶ID,訪問日期

  1. 1,2020-12-01 
  2. 1,2020-12-02 
  3. 1,2020-12-03 
  4. 1,2020-12-04 
  5. 1,2020-12-05 
  6. 1,2020-12-06 
  7. 1,2020-12-07 
  8. 1,2020-12-08 
  9. 1,2020-12-09 
  10. 1,2020-12-10 
  11. 2,2020-12-01 
  12. 2,2020-12-02 
  13. 2,2020-12-03 
  14. 2,2020-12-04 
  15. 2,2020-12-06 
  16. 2,2020-12-07 
  17. 2,2020-12-08 

下面是我們的建表語句

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

現(xiàn)在我們分析一下這個問題,怎么計算連續(xù)呢,計算肯定是針對同一個用戶的,然后我們可以按照用戶的訪問時間進行排序,然后我們用日期的數(shù)字減去對應(yīng)的排序就會得到一個值,如果訪問時間是連續(xù)的話,我們就可以得到同一個值

  1. select 
  2.     id,ctime, 
  3.     row_number(partition by id order by ctime ) as rn 
  4. from 
  5.     ods_user_log 

 

這里為了演示效果比較明顯,所以設(shè)計的數(shù)據(jù)有點特殊,大家可以看到對于id 是1的用戶,我們發(fā)現(xiàn)從12月1號到12月10號,我們的排名也依次是從1到10的,這個時候我們只要將日期變成對于的數(shù)字,然后減去對應(yīng)的排名它是等于20201200的,這個時候我們只需要統(tǒng)計20201200的個數(shù),這個個數(shù)就是連續(xù)登陸的天數(shù),這里我們就不把日期轉(zhuǎn)換成轉(zhuǎn)換成數(shù)字然后做減法了,我們直接使用日期去減。

  1. select 
  2.     id,ctime, 
  3.     date_sub(cast(ctime as date),row_number() over(partition by id order by ctime)), 
  4.     row_number() over(partition by id order by ctime ) as rn 
  5. from 
  6.     ods_user_log 

 

這下我再去統(tǒng)計每個用戶的相同日期有多少個即可,在我這里因為是7天,所以我只需要計算出相同日期的個數(shù)大于等于7即可

  1. select 
  2.     id,kt,count(1) as loginCnt 
  3. from ( 
  4.     select 
  5.         id,ctime, 
  6.         date_sub(cast(ctime as date),row_number() over(partition by id order by ctime)) as kt, 
  7.         row_number() over(partition by id order by ctime ) as rn 
  8.     from 
  9.         ods_user_log 
  10. ) tmp 
  11. group by 
  12.     id,kt 
  13. having 
  14.     count(1)>=7 

 

我們嘗試著理解一下這個數(shù)據(jù),它的意思就是用戶1 從(2020-11-30+1) 日開始,連續(xù)10天訪問了網(wǎng)站

這里有個問題需要注意一下,那就是上面我造的數(shù)據(jù)就是每天一條的,如果每天如果有多條,那我們上面的代碼就不對了,所以這個時候我們不是需要使用dense_rank,大家注意理解一下,我們需要的是去重,大家注意理解一下

分組抽樣

其實抽樣這個東西大家都接觸過,隨機抽樣也接觸過,今天我們學(xué)習(xí)一下分組隨機抽樣,其實實現(xiàn)很簡單,我們使用row_number 在子窗口內(nèi)隨機排序,然后抽出所需的樣本數(shù)據(jù)即可,我們還是用上面的數(shù)據(jù),每個用戶隨機抽取三天登陸

  1. select 
  2.     * 
  3. from ( 
  4.     select 
  5.         id,ctime, 
  6.         row_number() over(partition by id order by rand() ) as rn 
  7.     from 
  8.         ods_user_log 
  9. ) tmp 
  10. where rn<=3 

 

總結(jié)

rank() 排序相同時會重復(fù),總數(shù)不會變(會有間隙跳躍,數(shù)據(jù)不連續(xù))

dense_rank() 排序相同時會重復(fù),總數(shù)會減少(不會有間隙,數(shù)據(jù)連續(xù)的)

row_number() 會根據(jù)順序計算,不會重復(fù)不會減少

 

Row_number 函數(shù)常用的三種場景Top-N,計算連續(xù),分組抽樣

 

責(zé)任編輯:武曉燕 來源: Java大數(shù)據(jù)與數(shù)據(jù)倉庫
相關(guān)推薦

2018-12-14 12:07:53

Nginxweb服務(wù)器

2011-08-15 13:48:47

SQL ServerROW_NUMBER(

2023-12-24 22:30:05

LambdaJava函數(shù)

2021-05-21 12:36:16

限流代碼Java

2022-11-03 08:16:33

MySQL·窗口函數(shù)

2021-05-11 10:12:06

CIO軟件開發(fā)首席信息官

2019-11-27 14:56:35

關(guān)機電腦硬件

2022-08-01 08:36:09

upstream下游上游

2016-03-10 14:48:10

FedoraKorora 23Linux

2010-08-12 09:11:09

Flex彈出窗口

2019-10-31 10:25:19

算法Java數(shù)據(jù)結(jié)構(gòu)

2023-12-05 08:20:05

單例模式Python

2023-08-25 08:35:58

Rest方法字符串

2019-06-12 15:57:44

JVMCMSGC

2023-09-08 08:23:29

Servlet程序MVC

2020-10-13 08:40:01

CSS多行多列布局

2023-11-30 08:32:31

OpenFeign工具

2010-10-25 14:28:53

oracle trun

2010-10-25 16:52:48

oracle管道函數(shù)

2010-08-13 14:58:01

FlexNumber數(shù)據(jù)類型
點贊
收藏

51CTO技術(shù)棧公眾號