1. 程式人生 > >Hive 分析函式lead、lag例項應用

Hive 分析函式lead、lag例項應用

Lag和Lead分析函式可以在同一次查詢中取出同一欄位的後N行的資料(Lag)和前N行的資料(Lead)作為獨立的列。 這種操作可以代替表的自聯接,並且LAG和LEAD有更高的效率,其中over()表示當前查詢的結果集物件,括號裡面的語句則表示對這個結果集進行處理。 ## 1 LEAD 與LAG相反,LEAD(col,n,DEFAULT) 用於統計視窗內往下第n行值 引數1為列名,引數2為往下第n行(可選,預設為1),引數3為預設值(當往下第n行為NULL時候,取預設值,如不指定,則為NULL) ## 場景 使用者Peter在瀏覽網頁,在某個時刻,Peter點進了某個頁面,過一段時間後,Peter又進入了另外一個頁面,如此反覆,那怎麼去統計Peter在某個特定網頁的停留時間呢,又或是怎麼統計某個網頁使用者停留的總時間呢? ```sql create table test.user_log( userid string, time string, url string ) row format delimited fields terminated by '\t'; ``` 使用`load`命令將如下測試資料匯入: ``` 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`進入了網頁`url2`,即記錄的是進入網頁的時間。 ## 分析 要計算`Peter`在頁面`url1`停留的時間,需要用進入頁面`url2`的時間,減去進入`url1`的時間,即`2015-10-12 01:15:10`這個時間既是離開頁面`url1`的時間,也是開始進入頁面`url2`的時間。 獲取使用者在某個頁面停留的起始與結束時間: ```sql select userid, time stime, lead(time) over(partition by userid order by time) etime, url from test.user_log; ``` stime就是進入頁面時間,etime就是離開頁面時間,結果是這樣的: ``` Marry 2015-11-12 01:10:00 2015-11-12 01:15:10 url1 Marry 2015-11-12 01:15:10 2015-11-12 01:16:40 url2 Marry 2015-11-12 01:16:40 2015-11-12 02:13:00 url3 Marry 2015-11-12 02:13:00 2015-11-12 03:14:30 url4 Marry 2015-11-12 03:14:30 NULL url5 Peter 2015-10-12 01:10:00 2015-10-12 01:15:10 url1 Peter 2015-10-12 01:15:10 2015-10-12 01:16:40 url2 Peter 2015-10-12 01:16:40 2015-10-12 02:13:00 url3 Peter 2015-10-12 02:13:00 2015-10-12 03:14:30 url4 Peter 2015-10-12 03:14:30 NULL url5 ``` 用etime減去stime,然後按照使用者分組累加就是,每個使用者訪問的總時間了。 ```sql select userid, time stime, lead(time) over(partition by userid order by time) etime, UNIX_TIMESTAMP(lead(time) over(partition by userid order by time),'yyyy-MM-dd HH:mm:ss')- UNIX_TIMESTAMP(time,'yyyy-MM-dd HH:mm:ss') period, url from test.user_log; ``` 這裡展示出了stime(開始時間),etime(離開時間),period(停留時長),url(頁面地址),結果: ``` Marry 2015-11-12 01:10:00 2015-11-12 01:15:10 310 url1 Marry 2015-11-12 01:15:10 2015-11-12 01:16:40 90 url2 Marry 2015-11-12 01:16:40 2015-11-12 02:13:00 3380 url3 Marry 2015-11-12 02:13:00 2015-11-12 03:14:30 3690 url4 Marry 2015-11-12 03:14:30 NULL NULL url5 Peter 2015-10-12 01:10:00 2015-10-12 01:15:10 310 url1 Peter 2015-10-12 01:15:10 2015-10-12 01:16:40 90 url2 Peter 2015-10-12 01:16:40 2015-10-12 02:13:00 3380 url3 Peter 2015-10-12 02:13:00 2015-10-12 03:14:30 3690 url4 Peter 2015-10-12 03:14:30 NULL NULL url5 ``` - 這裡有空的情況,也就是沒有獲取到離開時間,這要看實際業務怎麼定義了,如果算到23點,太長了。 ## 2 Lag LAG(col,n,DEFAULT) 用於統計視窗內往上第n行值第一個引數為列名,第二個引數為往上第n行(可選,預設為1),第三個引數為預設值(當往上第n行為NULL時候,取預設值,如不指定,則為NULL)可以用來做一些時間的維護,如上一次登入時間。 ## 場景 使用者Peter在瀏覽網頁,在某個時刻,Peter點進了某個頁面,過一段時間後,Peter又進入了另外一個頁面,如此反覆,那怎麼去統計Peter在某個特定網頁的停留時間呢,又或是怎麼統計某個網頁使用者停留的總時間呢? ```sql create table test.user_log( userid string, time string, url string ) row format delimited fields terminated by '\t'; ``` 使用`load`命令將如下測試資料匯入: ``` 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`進入了網頁`url2`,即記錄的是進入網頁的時間。 ```sql select userid, time etime, lag(time, 1, '1970-01-01 00:00:00') over(partition by userid order by time) stime, url from test.user_log; ``` 這裡`etime`是結束時間,`stime`是開始時間,結果: ``` Marry 2015-11-12 01:10:00 1970-01-01 00:00:00 url1 Marry 2015-11-12 01:15:10 2015-11-12 01:10:00 url2 Marry 2015-11-12 01:16:40 2015-11-12 01:15:10 url3 Marry 2015-11-12 02:13:00 2015-11-12 01:16:40 url4 Marry 2015-11-12 03:14:30 2015-11-12 02:13:00 url5 Peter 2015-10-12 01:10:00 1970-01-01 00:00:00 url1 Peter 2015-10-12 01:15:10 2015-10-12 01:10:00 url2 Peter 2015-10-12 01:16:40 2015-10-12 01:15:10 url3 Peter 2015-10-12 02:13:00 2015-10-12 01:16:40 url4 Peter 2015-10-12 03:14:30 2015-10-12 02:13:00 url5 ``` 計算總時間,只需要用結束時間 - 開始時間,然後分組累加即可。 ```sql select userid, UNIX_TIMESTAMP(time, 'yyyy-MM-dd HH:mm:ss') - UNIX_TIMESTAMP(lag(time, 1, '1970-01-01 00:00:00') over(partition by userid order by time), 'yyyy-MM-dd HH:mm:ss'), url from test.user_log; ``` 結果 ``` Marry 1447290600 url1 Marry 310 url2 Marry 90 url3 Marry 3380 url4 Marry 3690 url5 Peter 1444612200 url1 Peter 310 url2 Peter 90 url3 Peter 3380 url4 Peter 3690 url5 ``` 因為有兩個我將預設值置為了`1970-01-01`,所以算出來比較大,實際工作中需要按照實際情況