日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

窗口函数_LAG()与LEAD() 详解

發布時間:2023/12/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 窗口函数_LAG()与LEAD() 详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自:Hive 窗口函數lead 和 lag(39)

補充:HIVE_HIVE函數_窗口函數_LAG()/LEAD() 詳解


lead 和 lag

前面我們學習的first_value和last_value 取的是排序后的數據截止當前行的第一行數據和最后一行數據

Lag和Lead分析函數可以在一次查詢中取出當前行后N行和前N行的數據,雖然可以不用排序,但是往往只有在排序的場景下取前面或者后面N 行數據才有意義

這種操作可以代替表的自聯接,并且LAG和LEAD有更高的效率。

Lag/Lead(col,n,DEFAULT) 用于統計窗口內當前行往前或者往后第n行值

  • 第一個參數為列名,
  • 第二個參數為往后/前第n行(可選,默認為1),
  • 第三個參數為默認值(當往上第n行為NULL時候,取默認值,如不指定,則為NULL)

需要注意的是lag 取得是當前行之前的數據,lead 取的實當前行之后的數據

測試數據

我們有這樣一個文本user_access_log.txt,里面記錄了用戶對頁面的訪問情況id,ctime,url 分別代表了用戶ID,訪問時間和訪問的頁面的URL

Peter 2015-10-12?01:10:00 url1 Peter 2015-10-12?01:15:10 url2 Peter 2015-10-12?01:16:40 url3 Peter 2015-10-12?02:13:00 url4 Peter 2015-10-12?03:14:30 url5 Marry 2015-11-12?01:10:00 url1 Marry 2015-11-12?01:15:10 url2 Marry 2015-11-12?01:16:40 url3 Marry 2015-11-12?02:13:00 url4 Marry 2015-11-12?03:14:30 url5

數據說明:Peter 2015-10-12 01:10:00 url1 ? ,表示Peter在2015-10-12 01:10:00進入了網頁url1,即記錄的是進入網頁的時間。

從例子中學習lead 和 lag

計算當前用戶的第一次訪問時間以及當前訪問時間的上一次訪問時間和下一次訪問時間

從描述我們知道了分區的條件或者子窗口的定義條件是用戶本身,從我們前面的學習中我們知道了第一次訪問時間我們可以使用first_value 計算,下面我們看一下這個需求如何實現

selectuserid,url,ctime,first_value(ctime) over(partition by userid order by ctime) as first_ctime,lag(ctime,1) over(partition by userid order by ctime) as lag_ctime,lead(ctime,1) over(partition by userid order by ctime) as lead_ctime from ods_user_log;

這里我們也對這個結果簡單分析一下,對于第一行數據它是沒有lag_ctime的,也就是沒有上一次訪問時間,因為它是第一次訪問,對于lead_ctime也就是下一次訪問時間2015-11-12 01:15:10

計算用戶在每個頁面上的停留時長

用戶Peter在瀏覽網頁,在某個時刻,Peter點進了某個頁面,過一段時間后,Peter又進入了另外一個頁面,如此反復,那怎么去統計Peter在某個特定網頁的停留時間呢,又或是怎么統計某個網頁用戶停留的總時間呢?

要計算Peter在頁面url1停留的時間,需要用進入頁面url2的時間,減去進入url1的時間,即2015-10-12 01:15:10這個時間既是離開頁面url1的時間,也是開始進入頁面url2的時間。所以我們需要先獲取用戶在某個頁面停留的起始與結束時間

selectuserid,url,ctime as startTime, lead(ctime,1) over(partition by userid order by ctime) as leaveTime from ods_user_log;

有了進入時間和離開時間我們就很容易計算出用戶在特定頁面上的停留時間,只需要用離開時間減去進入時間即可

selectuserid,url,ctime as startTime,lead(ctime,1) over(partition by userid order by ctime) as leaveTime,unix_timestamp(lead(ctime,1) over(partition by userid order by ctime) ) -unix_timestamp(ctime) as stayTime from ods_user_log;

大家考慮一個問題如果沒有lag和lead這樣的函數,我們該如何實現這個需求呢,我們可以借助自關聯來實現,但是這個自關聯就有很多種是想方式了,這里我借助row_number 來實現一種

with a as (select userid,url,ctime as startTime,row_number() over (partition by userid order by ctime ) as rnfromods_user_log ) select a1.userid userid,a1.startTime startTime,a2.startTime leaveTime,unix_timestamp(a2.startTime )-unix_timestamp(a1.startTime ) as stayTimefrom a a1 inner join a a2 on a1.userid=a2.useridand (a2.rn-a1.rn=1) ;

這里我們主要是使用 (a2.rn-a1.rn=1) 的條件找出了用戶進入頁面和離開頁面的時間

使用場景

lead 和 lag 的使用場景其實是比較多的,尤其我們在計算需要自關聯的這種場景下,如果合理使用頭是可以很好的提高我們程序的性能和簡化我們的寫法,下面我們再看一個例子

有個日志表中記錄了商戶費率變化狀態的所有信息用戶ID,費率,時間,現在有個需求,要取出按照時間軸順序,發生了費率變化的數據行,輸出數據格式商戶ID,當前時間,變化時間,原始費率,變化后的費率

100,0.1,2016-03-02 100,0.1,2016-02-02 100,0.2,2016-03-05 100,0.2,2016-03-06 100,0.3,2016-03-07 100,0.1,2016-03-09 100,0.1,2016-03-10 100,0.1,2016-03-10 200,0.1,2016-03-10 200,0.1,2016-02-02 200,0.2,2016-03-05 200,0.2,2016-03-06 200,0.3,2016-03-07 200,0.1,2016-03-09 200,0.1,2016-03-10 200,0.1,2016-03-10

現在我們開始建表

create table ods_user_rate_log(userid string,rate double,ctime string ) row format delimited fields terminated by ','; LOAD DATA LOCAL INPATH '/Users/liuwenqiang/workspace/hive/ods_user_rate_log.txt' OVERWRITE INTO TABLE ods_user_rate_log;

現在們分析一下,首先我們是單獨計每個商戶的,所以我們的子窗口定義條件就是用戶ID,然后我們跟蹤的是費率的隨時間的變化所以我們是要按照時間排序,最后我們需要的費率發生了變化的數據,所以我們需要比較一下原始費率和下一次費率

第一步:獲取當前費率和下一次的費率

select userid,ctime,rate, lead(rate,1) over (partition by userid order by ctime) new_rate from ods_user_rate_log;

第二步:找出費率不同的記錄然后返回,需要注意的是,我們還需要需要獲取到發生變化的時間

select * from(select userid,ctime,lead(ctime,1) over (partition by userid order by ctime) new_date,rate, lead(rate, 1) over (partition by userid order by ctime) new_rate from ods_user_rate_log) tmp where rate!=new_rate;

總結

  • lag和lead 主要用來計算當前行的前后N 行的這種場景,一般情況下我們會對數據進行排序,因為只有在有序的情況下,前面多少行和后面多少行才有意義

  • lag和lead 可以用在某些場景下代替自關聯的寫法

總結

以上是生活随笔為你收集整理的窗口函数_LAG()与LEAD() 详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。