Hive基于SQL创建漏斗模型
為了突出重點,總結就寫在最前面了。從拿到需求開始,我們經(jīng)歷了以下步驟來完成工作:
- 需求分析
- 設計測試數(shù)據(jù)集及測試用例
- 數(shù)據(jù)清洗
- 需要實現(xiàn)
- 測試
其中數(shù)據(jù)清洗主要是做了兩個工作:
實現(xiàn)的判斷依據(jù)如下:
- 亂序漏斗:訪問的頁面數(shù)小于4,或者頁面順序不對。
- 順序漏斗:訪問的頁面數(shù)等于4,且頁面順序嚴格對應。
- 順序間隔漏斗:訪問的頁面數(shù)等于4,且頁面順序嚴格對應,且訪問B頁面的時間-訪問A頁面的時間超過2小時。
實現(xiàn)過程中主要使用了下面的函數(shù):
rank
concat_ws
collect_set
split
unix_timestamp
子查詢
?
需求
概述
一般來說,客戶會按照A->B->C->D的順序來訪問頁面,而且越到后面的頁面訪問率就越低,比如A是網(wǎng)站首頁,B是列表頁,C是詳情頁,D是支付頁,根據(jù)常識,很容易知道A頁面的訪問率是最高的而D則是最低的。
現(xiàn)在有一個需求:使用SQL語句來完成以下的工作:
- 找出亂序訪問的用戶訪問記錄,即不按照A->B->C->D的順序訪問的
- 找出順序訪問的用戶訪問記錄,即嚴格按照A->B->C->D的順序訪問的
- 找出順序的并符合間隔條件的用戶訪問記錄,即嚴格按照A->B->C->D的順序訪問的,并且訪問A后超過2小時再訪問B的。
分析
這個需求表述的不是很清楚,我們再來明確一下各種情況應該怎么處理。
首先要完成這種數(shù)據(jù)漏斗,必須能夠將一個用戶的每次訪問嚴格的界定開來,即有辦法區(qū)分每個用戶的每次訪問都請求了哪些網(wǎng)址,這項工作顯然不應該是我們這次的任務,故假定數(shù)據(jù)集符合該要求。
其次,還有一些特殊的情況的處理需要進一步明確:
- 如果一個用戶在訪問下一個頁面之前多次訪問上一個頁面應該如何處理間隔?如A->A->B->C->D
- 如果一個用戶按照順序訪問完后又重新訪問某個頁面應該如何處理?是算順序還是逆序?如A->B->C->D->C
對于第1個問題,按照最后一次訪問的時間為準;對于第2個問題,則約定其為亂序訪問。
數(shù)據(jù)集及測試用例
? ? ? ? 我們并沒有現(xiàn)成的數(shù)據(jù)集可以使用。為了說明問題,需要我們自己創(chuàng)建一個數(shù)據(jù)集用于測試。
表結構設計
? ? ? ? 為了說明問題方便,在不影響結論的情況下,應該讓表結構盡可能的簡單。必須的字段包括:
- session_id 用于界定每個用戶的一次訪問,在一次訪問中的多個請求該字段相同
- url 請求鏈接地址
- req_time 訪問頁面的時間
- 測試數(shù)據(jù)
用等價類劃分法來給一些測試數(shù)據(jù)。等價類大概劃成下面這樣:
基于這樣的等價類劃分,可以給出下面的測試數(shù)據(jù)集:
頁面無缺失,順序,超過間隔,無重復頁面 session_id req_url req_time s_01 a.html 2017-03-26 08:00:00 s_01 b.html 2017-03-26 10:01:00 s_01 c.html 2017-03-26 10:03:00 s_01 d.html 2017-03-26 10:04:00頁面無缺失,順序,超過間隔,有重復頁面 session_id req_url req_time s_02 a.html 2017-03-26 08:00:00 s_02 a.html 2017-03-26 09:00:00 s_02 b.html 2017-03-26 11:01:00 s_02 c.html 2017-03-26 11:03:00 s_02 d.html 2017-03-26 11:04:00頁面無缺失,順序,間隔不足,無重復頁面 session_id req_url req_time s_03 a.html 2017-03-26 08:00:00 s_03 b.html 2017-03-26 09:01:00 s_03 c.html 2017-03-26 09:03:00 s_03 d.html 2017-03-26 09:04:00頁面無缺失,順序,間隔不足,有重復頁面 session_id req_url req_time s_04 a.html 2017-03-26 08:00:00 s_04 a.html 2017-03-26 09:00:00 s_04 b.html 2017-03-26 10:01:00 s_04 c.html 2017-03-26 10:03:00 s_04 d.html 2017-03-26 10:04:00頁面無缺失,順序訪問完后亂序,超過間隔,有重復頁面 session_id req_url req_time s_05 a.html 2017-03-26 08:00:00 s_05 b.html 2017-03-26 10:01:00 s_05 c.html 2017-03-26 10:03:00 s_05 d.html 2017-03-26 10:04:00 s_05 c.html 2017-03-26 11:04:00頁面無缺失,順序訪問完后亂序,間隔不足,有重復頁面 session_id req_url req_time s_06 a.html 2017-03-26 09:00:00 s_06 b.html 2017-03-26 10:01:00 s_06 c.html 2017-03-26 10:03:00 s_06 d.html 2017-03-26 10:04:00 s_06 c.html 2017-03-26 11:04:00頁面無缺失,其他亂序,超過間隔,有重復頁面 session_id req_url req_time s_07 a.html 2017-03-26 07:00:00 s_07 b.html 2017-03-26 10:01:00 s_07 c.html 2017-03-26 10:03:00 s_07 d.html 2017-03-26 10:04:00 s_07 c.html 2017-03-26 11:04:00頁面無缺失,其他亂序,超過間隔,無重復頁面 session_id req_url req_time s_08 a.html 2017-03-26 07:00:00 s_08 c.html 2017-03-26 10:01:00 s_08 b.html 2017-03-26 10:03:00 s_08 d.html 2017-03-26 10:04:00頁面無缺失,其他亂序,間隔不足,有重復頁面 session_id req_url req_time s_09 a.html 2017-03-26 09:00:00 s_09 b.html 2017-03-26 10:01:00 s_09 c.html 2017-03-26 10:03:00 s_09 d.html 2017-03-26 10:04:00 s_09 c.html 2017-03-26 11:04:00頁面無缺失,其他亂序,間隔不足,無重復頁面 session_id req_url req_time s_10 a.html 2017-03-26 09:00:00 s_10 c.html 2017-03-26 10:01:00 s_10 b.html 2017-03-26 10:03:00 s_10 d.html 2017-03-26 10:04:00頁面缺失,其他亂序,超過間隔,有重復頁面 session_id req_url req_time s_11 a.html 2017-03-26 07:00:00 s_11 b.html 2017-03-26 10:03:00 s_11 d.html 2017-03-26 10:04:00 s_11 d.html 2017-03-26 11:04:00頁面缺失,其他亂序,超過間隔,無重復頁面 session_id req_url req_time s_12 a.html 2017-03-26 07:00:00 s_12 b.html 2017-03-26 10:03:00 s_12 d.html 2017-03-26 10:04:00頁面缺失,其他亂序,間隔不足,有重復頁面 session_id req_url req_time s_13 a.html 2017-03-26 07:00:00 s_13 d.html 2017-03-26 10:04:00 s_13 d.html 2017-03-26 11:04:00頁面缺失,其他亂序,間隔不足,無重復頁面 session_id req_url req_time s_14 a.html 2017-03-26 07:00:00 s_14 d.html 2017-03-26 10:04:00測試用例
有了數(shù)據(jù)集,我們就可以給出下面的測試
?
| ? ? ? ? ? ? ? ? ?亂序漏斗 | s_05 s_06 s_07 s_08 s_09 s_10 s_11 s_12 s_13 s_14 | ? |
| 順序漏斗 | ? ? ? ? ? ? ? ? ? ? ? ? ? ? s_01 | ? |
| 順序間隔漏斗 | s_01 s_02 | ? |
準備工作
完成了需求分析以及測試數(shù)據(jù)和測試用例的準備以后,我們就可以開始實現(xiàn)這幾個數(shù)據(jù)漏斗了。
使用下面的命令在Hive中創(chuàng)建一個表,用于存放用戶訪問數(shù)據(jù)。
use test_db;create table t_visitlog(session_id string,req_url string,req_time timestamp) row format delimited fields terminated by ',';然后創(chuàng)建一個數(shù)據(jù)文件,visitlog.data,輸入下面的內(nèi)容:
s_01,a.html,2017-03-26 08:00:00 s_01,b.html,2017-03-26 10:01:00 s_01,c.html,2017-03-26 10:03:00 s_01,d.html,2017-03-26 10:04:00 s_02,a.html,2017-03-26 08:00:00 s_02,a.html,2017-03-26 09:00:00 s_02,b.html,2017-03-26 11:01:00 s_02,c.html,2017-03-26 11:03:00 s_02,d.html,2017-03-26 11:04:00 s_03,a.html,2017-03-26 08:00:00 s_03,b.html,2017-03-26 09:01:00 s_03,c.html,2017-03-26 09:03:00 s_03,d.html,2017-03-26 09:04:00 s_04,a.html,2017-03-26 08:00:00 s_04,a.html,2017-03-26 09:00:00 s_04,b.html,2017-03-26 10:01:00 s_04,c.html,2017-03-26 10:03:00 s_04,d.html,2017-03-26 10:04:00 s_05,a.html,2017-03-26 08:00:00 s_05,b.html,2017-03-26 10:01:00 s_05,c.html,2017-03-26 10:03:00 s_05,d.html,2017-03-26 10:04:00 s_05,c.html,2017-03-26 11:04:00 s_06,a.html,2017-03-26 09:00:00 s_06,b.html,2017-03-26 10:01:00 s_06,c.html,2017-03-26 10:03:00 s_06,d.html,2017-03-26 10:04:00 s_06,c.html,2017-03-26 11:04:00 s_07,a.html,2017-03-26 07:00:00 s_07,b.html,2017-03-26 10:01:00 s_07,c.html,2017-03-26 10:03:00 s_07,d.html,2017-03-26 10:04:00 s_07,c.html,2017-03-26 11:04:00 s_08,a.html,2017-03-26 07:00:00 s_08,c.html,2017-03-26 10:01:00 s_08,b.html,2017-03-26 10:03:00 s_08,d.html,2017-03-26 10:04:00 s_09,a.html,2017-03-26 09:00:00 s_09,b.html,2017-03-26 10:01:00 s_09,c.html,2017-03-26 10:03:00 s_09,d.html,2017-03-26 10:04:00 s_09,c.html,2017-03-26 11:04:00 s_10,a.html,2017-03-26 09:00:00 s_10,c.html,2017-03-26 10:01:00 s_10,b.html,2017-03-26 10:03:00 s_10,d.html,2017-03-26 10:04:00 s_11,a.html,2017-03-26 07:00:00 s_11,b.html,2017-03-26 10:03:00 s_11,d.html,2017-03-26 10:04:00 s_11,d.html,2017-03-26 11:04:00 s_12,a.html,2017-03-26 07:00:00 s_12,b.html,2017-03-26 10:03:00 s_12,d.html,2017-03-26 10:04:00 s_13,a.html,2017-03-26 07:00:00 s_13,d.html,2017-03-26 10:04:00 s_13,d.html,2017-03-26 11:04:00 s_14,a.html,2017-03-26 07:00:00 s_14,d.html,2017-03-26 10:04:00然后使用下面的命令將其上傳到hdfs中。
hadoop fs -put visitlog.data /user/hive/warehouse/test_db.db/t_visitlog/然后使用下面的SQL語句檢查是否上傳成功:
select * from t_visitlog;我這邊是上傳成功的。到這里我們就完成了準備工作。
數(shù)據(jù)清洗
接下來,我們要將數(shù)據(jù)進行一些處理,使得后面的工作更容易開展,主要工作包括:
去掉重復的頁面記錄
使用下面的SQL語句即可實現(xiàn)去掉每一次訪問中重復的頁面記錄,同時只保留每個頁面最后一次訪問記錄。
?
為了粘貼方便,這里就不縮進了。
為了方便后續(xù)的操作,我們使用下面的SQL語句將查詢結果放到一個新的表t_vlog_norepeat中。
使用下面的命令來查看一下新創(chuàng)建的表的結構:
desc t_vlog_norepeat;
輸出結果如下:
session_id string req_url string req_time timestamp是符合我們要求的。
合并訪問記錄
使用下面的命令將訪問記錄保存到t_vlog_merge表中去。
create table t_vlog_merge as select session_id,concat_ws(',',collect_set(vr)) as vtext from(select distinct session_id,concat_ws('_',cast(req_time as string),req_url) as vr from (select session_id,req_url,req_time from t_vlog_norepeat sort by session_id,req_time asc)a ) temp group by session_id;結果如下:
s_01 2017-03-26 08:00:00_a.html,2017-03-26 10:01:00_b.html,2017-03-26 10:03:00_c.html,2017-03-26 10:04:00_d.html s_02 2017-03-26 09:00:00_a.html,2017-03-26 11:01:00_b.html,2017-03-26 11:03:00_c.html,2017-03-26 11:04:00_d.html s_03 2017-03-26 08:00:00_a.html,2017-03-26 09:01:00_b.html,2017-03-26 09:03:00_c.html,2017-03-26 09:04:00_d.html s_04 2017-03-26 09:00:00_a.html,2017-03-26 10:01:00_b.html,2017-03-26 10:03:00_c.html,2017-03-26 10:04:00_d.html s_05 2017-03-26 08:00:00_a.html,2017-03-26 10:01:00_b.html,2017-03-26 10:04:00_d.html,2017-03-26 11:04:00_c.html s_06 2017-03-26 09:00:00_a.html,2017-03-26 10:01:00_b.html,2017-03-26 10:04:00_d.html,2017-03-26 11:04:00_c.html s_07 2017-03-26 07:00:00_a.html,2017-03-26 10:01:00_b.html,2017-03-26 10:04:00_d.html,2017-03-26 11:04:00_c.html s_08 2017-03-26 07:00:00_a.html,2017-03-26 10:01:00_c.html,2017-03-26 10:03:00_b.html,2017-03-26 10:04:00_d.html s_09 2017-03-26 09:00:00_a.html,2017-03-26 10:01:00_b.html,2017-03-26 10:04:00_d.html,2017-03-26 11:04:00_c.html s_10 2017-03-26 09:00:00_a.html,2017-03-26 10:01:00_c.html,2017-03-26 10:03:00_b.html,2017-03-26 10:04:00_d.html s_11 2017-03-26 07:00:00_a.html,2017-03-26 10:03:00_b.html,2017-03-26 11:04:00_d.html s_12 2017-03-26 07:00:00_a.html,2017-03-26 10:03:00_b.html,2017-03-26 10:04:00_d.html s_13 2017-03-26 07:00:00_a.html,2017-03-26 11:04:00_d.html s_14 2017-03-26 07:00:00_a.html,2017-03-26 10:04:00_d.html實現(xiàn)
實現(xiàn)亂序漏斗
我們來分析一下亂序漏斗的幾個特征,第1個是按照”,”分割后長度不為4,第2個就是按照”,”分割后頁面順序不對。
使用下面的代碼即可實現(xiàn)亂序漏斗:
select session_id from(select session_id,vtext,split(vtext,',') as arr from t_vlog_merge ) temp where size(arr) != 4 or split(arr[0],'_')[1] != 'a.html' or split(arr[1],'_')[1] != 'b.html' or split(arr[2],'_')[1] != 'c.html' or split(arr[3],'_')[1] != 'd.html';結果:
s_05 s_06 s_07 s_08 s_09 s_10 s_11 s_12 s_13 s_14實現(xiàn)順序漏斗
使用下面的代碼即可實現(xiàn)順序漏斗:
select session_id from(select session_id,vtext,split(vtext,',') as arr from t_vlog_merge ) temp where size(arr) == 4 and split(arr[0],'_')[1] == 'a.html' and split(arr[1],'_')[1] == 'b.html' and split(arr[2],'_')[1] == 'c.html' and split(arr[3],'_')[1] == 'd.html';結果:
s_01 s_02 s_03 s_04實現(xiàn)順序間隔漏斗
使用下面的代碼可以實現(xiàn)順序間隔漏斗(訪問A頁面2小時以后訪問B):
select session_id from(select session_id,vtext,split(vtext,',') as arr from t_vlog_merge ) temp where size(arr) == 4 and split(arr[0],'_')[1] == 'a.html' and split(arr[1],'_')[1] == 'b.html' and split(arr[2],'_')[1] == 'c.html' and split(arr[3],'_')[1] == 'd.html' and unix_timestamp(split(arr[1],'_')[0]) - unix_timestamp(split(arr[0],'_')[0]) > 7200;結果:
s_01 s_02測試
上面已經(jīng)測試過了,測試結果如下:
| 亂序漏斗 | s_05 s_06 s_07 s_08 s_09 s_10 s_11 s_12 s_13 s_14 | s_05 s_06 s_07 s_08 s_09 s_10 s_11 s_12 s_13 s_14 |
| 順序漏斗 | s_01 s_02 s_03 s_04 | s_01 s_02 s_03 s_04 |
| 順序間隔漏斗 | s_01 s_02 | s_01 s_02 |
?
總結
以上是生活随笔為你收集整理的Hive基于SQL创建漏斗模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 热销商品和商品详情
- 下一篇: MySQL中时间日期类型的使用