0. 需求
我們有如下的用戶訪問數據
userId visitDate visitCount
u01 2017/1/21 5
u02 2017/1/23 6
u03 2017/1/22 8
u04 2017/1/20 3
u01 2017/1/23 6
u01 2017/2/21 8
U02 2017/1/23 6
U01 2017/2/22 4
要求使用SQL統計出每個用戶的累積訪問次數,如下表所示:
用戶id 月份 小計 累積
u01 2017-01 11 11
u01 2017-02 12 23
u02 2017-01 12 12
u03 2017-01 8 8
u04 2017-01 3 3
1.實現
窗口函數典型案例
(1) 數據準備
u01 2017/1/21 5
u02 2017/1/23 6
u03 2017/1/22 8
u04 2017/1/20 3
u01 2017/1/23 6
u01 2017/2/21 8
u02 2017/1/23 6
u01 2017/2/22 4
(2)創建hive表
CREATE TABLE dan_test.sqltest1 (
userId string,
visitDate string,
visitCount string )
ROW format delimited FIELDS TERMINATED BY "\t";
load data local inpath "/home/centos/dan_test/sqltest1.txt" into table sqltest1;
(3)需求實現
① 將時間進行格式化,轉換成題目要求的時間
採用date_format函數+regexp_replace函數
select date_format(regexp_replace(visitdate,'/','-'),'yyyy-MM') from sqltest1
hive> select date_format(regexp_replace(visitdate,'/','-'),'yyyy-MM') from sqltest1;
OK
2017-01
2017-01
2017-01
2017-01
2017-01
2017-02
2017-01
2017-02
Time taken: 0.15 seconds, Fetched: 8 row(s)
轉換日期作爲子表
SELECT userid
,date_format(regexp_replace(visitdate,'/','-'),'yyyy-MM') AS visitmonth
,visitcount
FROM sqltest1
② 分析函數+窗口函數實現
注意求用戶每月彙總額的時候注意去重,如不去重則是如下結果。爲什麼需要去重?因爲窗口函數作用的是每條記錄,在每條記錄的後面都會形成結果,其分析函數,分析的範圍是over()函數中所指定的,這一點一定要弄明白
select t.userid as userid
,t.visitmonth as visitmonth
,sum(t.visitcount) over(partition BY userid,visitmonth) as sum_per_month
from
(
SELECT userid
,date_format(regexp_replace(visitdate,'/','-'),'yyyy-MM') AS visitmonth
,visitcount
FROM sqltest1
)t
本題最終的結果如下:
select s.userid
,s.visitmonth
,s.sum_per_month
,sum(s.sum_per_month) over(partition BY s.userid order by s.visitmonth) as total_visitcount
from
(
select distinct t.userid as userid
,t.visitmonth as visitmonth
,sum(t.visitcount) over(partition BY userid,visitmonth) as sum_per_month
from
(
SELECT userid
,date_format(regexp_replace(visitdate,'/','-'),'yyyy-MM') AS visitmonth
,visitcount
FROM sqltest1
)t
)s
2 小 結
本題主要的使用知識點歸納如下:
- (1)regexp_replace函數的使用
- (2)date_format函數的使用
- (3)窗口函數與分析函數的結合使用。當然本題也可以不用窗口函數分析,也可以使用group by完成,讀者自行嘗試