HiveSQL例題-常用函數與基礎語法講解

我們通過一些簡單的案例來講解Hive的常用基礎語法以及一些常用的函數。

學習目標:
1. 掌握HIVE基礎語法、常用函數及其組合使用
2. 掌握一些基本業務指標的分析思路與實現技巧

1、基礎語法:

SELECT …A… FROM …B… WHERE …C…

  • A:列名
  • B:表名
  • C:篩選條件

需求1:
某次經營活動中,商家發起了"異性拼團購",試着針對某個地區的用戶進行推廣,找出匹配用戶。
思考:
根據需求,我們可以參考實現選出地區城市在北京,性別爲女的10個用戶名來進行匹配。這個實現可以有很多種,按照你所想的去實現需求即可。

SELECT user_name
FROM user_info
WHERE city='beijing' and sex='female'
limit 10;

limit 10 代表只展現前10行數據。
需求2:
某天,發現食物類的商品賣的很好,你能找出幾個資深喫貨嗎?
思考:
商品種類有很多種,這裏需要展現食物類的商品,那麼我們挑選具體的某一天看看用戶購買食物類商品的數量,金額。我們選在2019年6月18日,購買的商品品類是food的用戶名、購買數量、支付金額

SELECT user_name,piece,pay_amount
FROM user_trade
WHERE dt='2019-06-18' and goods_category='food' ;

注意:如果該表是一個分區表,則WHERE條件中必須對分區字段進行限
制。

GROUP BY
分組函數:分類彙總

需求3:
試着對本公司2019年第一季度商品的熱度與價值度進行分析。
思考:
首先篩選條件,需求需要的是2019年第一季度,那麼我們選擇2019年的1月-3月,商品的熱度和價值度要看你怎麼理解,這裏我們通過查看不同類商品的購買人數和購買金額來分析。

SELECT goods_category,
count(distinct user_name) as user_num,
sum(pay_amount) as total_amount
FROM user_trade
WHERE dt between '2019-01-01' and '2019-03-31'
GROUP BY goods_category;

這裏的不同類商品我們就用到了分組函數group by 來實現。
distinct 去重、count 計數、sum 求和、between...and... 兩者之間
這裏給大家整理一下常用的聚合函數:

  1. count():計數 count(distinct ……) 去重計數
  2. sum():求和
  3. avg():平均值
  4. max():最大值
  5. min():最小值

GROUP BY …… HAVING
HAVING:對GROUP BY的對象進行篩選,是對聚合結果進行篩選而不是對
原表進行篩選。

需求4-1:
2019年4月,支付金額超過5萬元的用戶。給VIP用戶贈送優惠劵。
思考:
直接篩選2019年4月,計算支付金額,統計支付金額大於5萬元的用戶。

SELECT user_name,
sum(pay_amount) as total_amount
FROM user_trade
WHERE dt between '2019-04-01' and '2019-04-30'
GROUP BY user_name
HAVING sum(pay_amount)>50000;

HAVING對聚合函數結果進行篩選。

ORDER BY
ASC:升序(默認,不寫的時候默認就是升序)
DESC:降序
對多個字段進行排序:ORDER BY A ASC , B DESC 每個字段都要指定
升序還是降序!

需求4-2:
2019年4月,支付金額最多的TOP5用戶
思考:
直接篩選2019年4月,統計支付總額,選出前5名用戶。

SELECT user_name,
sum(pay_amount) as total_amount
FROM user_trade
WHERE dt between '2019-04-01' and '2019-04-30'
GROUP BY user_name
ORDER BY total_amount DESC
limit 5;

注意:
爲什麼ORDER BY 後面不直接寫sum(pay_amount)而是用total_amount?
不可以寫:ORDER BY sum(pay_amount) DESC
——原因:執行順序!!!ORDER BY的執行順序在SELECT之後,所以需
使用重新定義的列名進行排序。

執行順序

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY

2、常用函數:

(1)如何把時間戳轉化爲日期?

在這裏插入圖片描述
可以看到user_trade這張表中字段pay_time是時間戳類型的值。
例:

 SELECT pay_time,
from_unixtime(pay_time,'yyyy-MM-dd hh:mm:ss')
FROM user_trade
WHERE dt='2019-04-09';

from_unixtime(bigint unixtime, string format):將時間戳轉化爲 指定格式的日期,bigint unixtime時間戳的字段名
format:

  1. yyyy-MM-dd hh:mm:ss
  2. yyyy-MM-dd hh
  3. yyyy-MM-dd hh:mm
  4. yyyyMMdd

有把時間戳轉換爲日期格式,那麼也有將日期轉換爲時間戳
利用 unix_timestamp 進行轉換

(2)如何計算日期間隔?

需求5:
去年的勞動節新用戶推廣活動價值分析。即拉新分析。
思考:
勞動節的推廣活動分析,那麼我們可以統計用戶的首次激活時間與2019年5月1日的日期間隔。

select user_name,datediff('2019-05-01',to_date(firstactivetime))
from user_info
limit 10;

拓展:日期增加函數、減少函數——date_add、date_sub(類型要是string類型的)

date_add(string startdate, int days)
date_sub (string startdate, int days)

(3)條件函數:
case when

需求6:
對用戶的年齡段進行分析,觀察分佈情況。
思考:
我們統計以下四個年齡段:20歲以下、20-30歲、30-40歲、40歲以上的
用戶數。

SELECT case when age<20 then '20歲以下'
when age>=20 and age<30 then '20-30歲'
when age>=30 and age<40 then '30-40歲'
else '40歲以上' end as age_type,
count(distinct user_id) user_num
FROM user_info
GROUP BY case when age<20 then '20歲以下'
when age>=20 and age<30 then '20-30歲'
when age>=30 and age<40 then '30-40歲'
else '40歲以上' end;
if

需求7:
去年王思聰的微博抽獎活動引起爭議,我們想要觀察用戶等級隨性別的
分佈情況。
思考:
用戶等級隨性格的分佈情況,我們統計每個性別用戶等級高低的分佈情況(level大於5爲高級)

SELECT sex,
if(level>5,'高','低') as level_type,
count(distinct user_id) user_num
FROM user_info
GROUP BY sex,
if(level>5,'高','低');
(4)字符串函數:

需求8:
分析每個月的拉新情況,可以倒推回運營效果。

SELECT substr(firstactivetime,1,7) as month,
count(distinct user_id) user_num
FROM user_info
GROUP BY substr(firstactivetime,1,7);

substr(string A, int start, int len)字符串截取
備註:如果不指定截取長度,則從起始位一直截取到最後。
需求9:
不同手機品牌的用戶數:

extra1(string):
{“systemtype”:“ios”,“education”:“master”,“marriage_status”:“1”,“phone
brand”:“iphone X”} extra2(map<string,string>):
{“systemtype”:“ios”,“education”:“master”,“marriage_status”:“1”,“phone
brand”:“iphone X”}
這是表中的兩個拓展字段,extra1字段中的信息是json類型的數據,extra2中是map類型的數據。

第一種寫法:是通過json字符串進行抽取數據

SELECT get_json_object(extra1, '$.phonebrand') as
phone_brand,
count(distinct user_id) user_num
FROM user_info
GROUP BY get_json_object(extra1, '$.phonebrand');

get_json_object(string json_string, string path)
param1:需要解析的json字段
param2:用$.key取出想要獲取的value

第二種寫法:通過鍵值對取數據,針對map類型數據

SELECT extra2['phonebrand'] as phone_brand,
count(distinct user_id) user_num
FROM user_info
GROUP BY extra2['phonebrand'];
(5)聚合統計函數:

練習:
ELLA用戶的2018年的平均每次支付金額,以及2018年最大的支付
日期與最小的支付日期的間隔

SELECT avg(pay_amount) as avg_amount,
datediff(max(from_unixtime(pay_time,'yyyy-MMdd')),
min(from_unixtime(pay_time,'yyyy-MM-dd')))
FROM user_trade
WHERE year(dt)='2018' and user_name='ELLA';

max(from_unixtime(pay_time,‘yyyy-MM-
dd’))=from_unixtime(max(pay_time),‘yyyy-MM-dd’))
datediff(max(pay_time),min(pay_time))

練習:

需求10:
找出在2018年具有VIP潛質的用戶,發送VIP試用劵。
思考:
具有VIP潛質的用戶,我們可以理解爲購買商品的種類比較多的用戶有可能發展爲VIP用戶,我們統計2018年購買的商品品類在兩個以上的用戶數。

SELECT count(a.user_name)
FROM
(SELECT user_name,
count(distinct goods_category) as category_num
FROM user_trade
WHERE year(dt)='2018'
GROUP BY user_name
HAVING count(distinct goods_category)>2) a;

思路流程:
三步走:
第一步:先求出每個人購買的商品品類數
第二步:篩選出購買商品品類數大於2的用戶
第三步:統計符合條件的用戶有多少個

需求11:
用戶激活時間在2018年,年齡段在20-30歲和30-40歲的婚姻狀況分佈。
思考、流程:
第一步:先選出激活時間在2018年的用戶,並把他們所在的年齡段計算
好,並提取出婚姻狀況
第二步:取出年齡段在20-30歲和30-40歲的用戶,把他們的婚姻狀況轉義
成可理解的說明
第三步:聚合計算,針對年齡段、婚姻狀況的聚合

SELECT a.age_type,
if(a.marriage_status=1,'已婚','未婚'),
count(distinct a.user_id)
FROM
(SELECT case when age<20 then '20歲以下'
when age>=20 and age<30 then '20-30歲'
when age>=30 and age<40 then '30-40歲'
else '40歲以上' end as age_type,
get_json_object(extra1, '$.marriage_status') as
marriage_status,
user_id
FROM user_info
WHERE to_date(firstactivetime) between '2018-01-01'
and '2018-12-31') a
WHERE a.age_type in ('20-30歲','30-40歲')
GROUP BY a.age_type,
if(a.marriage_status=1,'已婚','未婚');

需求12:
激活天數距今超過300天的男女分佈情況。

select sex,count(distinct user_name)
from user_info where datediff('2020-03-23',to_date(firstactivetime)) > 300
group by sex;

需求13:
不同性別、教育程度的分佈情況。

select sex,get_json_object(extra1,'$.education') as user_edu,count(distinct user_name) as user_num
from user_info
group by sex,get_json_object(extra1,'$.education');
select sex,extra2['education'],count(distinct user_id)
from user_info
group by sex,extra2['education'];

需求14:
2019年1月1日到2019年4月30日,每個時段的不同品類購買金額分佈。
select substr(from_unixtime(pay_time,‘yyyy-MM-dd HH’),12) as user_time,goods_category,sum(pay_amount)
from user_trade
where dt between ‘2019-01-01’ and ‘2019-04-30’
group by substr(from_unixtime(pay_time,‘yyyy-MM-dd HH’),12),goods_category;

總結:
1、利用group by做聚合計算。
2、利用order by做排序。
3、牢記SQL的執行順序。
4、常用函數組合的使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章