Hive(8)-常用查詢函式
一. 空欄位賦值
1. 函式說明
NVL:給值為NULL的資料賦值,它的格式是NVL( value,default_value)。它的功能是如果value為NULL,則NVL函式返回default_value的值,否則返回value的值,如果兩個引數都為NULL ,則返回NULL。
2. 案例
-- 如果員工的comm為NULL,則用-1代替 select comm,nvl(comm, -1) from emp;
-- 如果員工的comm為NULL,則用領導id代替 select comm, nvl(comm,mgr) from emp;
二. case when
1. 函式說明
2. 案例
-- 求出不同部門男女各多少人 select dept_id, sum(case sex when '男' then 1 else 0 end) male_sum, sum(case sex when '女' then 1 else 0 end) female_sum from emp_sex group by dept_id;
三. 行轉列(concat)
1. 函式說明
CONCAT(string A/col, string B/col…):返回輸入字串連線後的結果,支援任意個輸入字串;
CONCAT_WS(separator, str1, str2,...):它是一個特殊形式的 CONCAT()。第一個引數是剩餘引數間的分隔符。分隔符可以是與剩餘引數一樣的字串。如果分隔符是 NULL,返回值也將為 NULL。這個函式會跳過分隔符引數後的任何 NULL 和空字串。分隔符將被加到被連線的字串之間;
COLLECT_SET(col):函式只接受基本資料型別,它的主要作用是將某欄位的值進行去重彙總,產生array型別欄位。
2.案例
將血型和星座一樣的歸類到一起
select tmp_t.base, concat_ws("|",collect_set(tmp_t.name)) name from( select concat(constellation,",",blood_type) base, name from person_info ) tmp_t group by tmp_t.base;
四. 列轉行(explode)
1.函式說明
EXPLODE(col):將hive一列中複雜的array或者map結構拆分成多行。
LATERAL VIEW :
用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias
解釋:用於和split, explode等UDTF一起使用,它能夠將一列資料拆成多行資料,在此基礎上可以對拆分後的資料進行聚合。
2.案例
將電影分類中的陣列資料展開
select movie, cat_name from movie_info lateral view explode(category) exp_tbl as cat_name;
五. 視窗函式(開窗函式)
1. 語法
UDAF() over (PARTITION By col1,col2 order by col3 視窗子句(rows between .. and ..)) AS 列別名
注意:PARTITION By後可跟多個欄位,order By只跟一個欄位。
2. 函式說明
over()決定了聚合函式的聚合範圍,預設對整個視窗中的資料進行聚合,聚合函式對每一條資料呼叫一次。
partition by子句:使用Partiton by子句對資料進行分割槽,可以用paritition by對區內的進行聚合。
order by子句作用:對分割槽中的資料進行排序;確定聚合哪些行(預設從起點到當前行的聚合)
視窗子句
CURRENT ROW:當前行
n PRECEDING:往前n行資料
n FOLLOWING:往後n行資料
UNBOUNDED:起點,UNBOUNDED PRECEDING 表示從前面的起點, UNBOUNDED FOLLOWING表示到後面的終點
LAG(col,n,default_val):往前第n行資料
LEAD(col,n, default_val):往後第n行資料
NTILE(n):把有序分割槽中的行分發到指定資料的組中,各個組有編號,編號從1開始,對於每一行,NTILE返回此行所屬的組的編號。注意:n必須為int型別。
tips:
通過使用partition by子句將資料進行了分割槽。如果想要對視窗進行更細的動態劃分,就要引入視窗子句。
order by必須跟在partition by後;Rows必須跟在Order by子;(partition by .. order by)可替換為(distribute by .. sort by ..)
什麼時候用開窗函式?
開窗函式常結合聚合函式使用,一般來講聚合後的行數要少於聚合前的行數,但是有時我們既想顯示聚集前的資料,
又要顯示聚集後的資料,這時我們便引入了視窗函式.
3.案例
1). 查詢在2017年4月份購買過的顧客及總人數
select name, count(1) over() from business where orderdate like "2017-04-%" group by name;
2). 查詢顧客的購買明細及月購買總額
select name, orderdate, cost, sum(cost) over(partition by month(orderdate)) from business;
3). 將每個顧客的cost按照日期進行累加
select name,orderdate,cost, sum(cost) over() as sample1,--所有行相加 sum(cost) over(partition by name) as sample2,--按name分組,組內資料相加 sum(cost) over(partition by name order by orderdate) as sample3,--按name分組,組內資料累加 sum(cost) over(partition by name order by orderdate rows between UNBOUNDED PRECEDING and current row ) as sample4 ,--和sample3一樣,由起點到當前行的聚合 sum(cost) over(partition by name order by orderdate rows between 1 PRECEDING and current row) as sample5, --當前行和前面一行做聚合 sum(cost) over(partition by name order by orderdate rows between 1 PRECEDING AND 1 FOLLOWING ) as sample6,--當前行和前邊一行及後面一行 sum(cost) over(partition by name order by orderdate rows between current row and UNBOUNDED FOLLOWING ) as sample7 --當前行及後面所有行 from business;
4). 檢視顧客上次的購買時間
select name,orderdate,cost, lag(orderdate,1,'first_buy') over(partition by name order by orderdate ) from business;
5). 查詢前20%時間的訂單資訊
select * from ( select name,orderdate,cost, ntile(5) over(order by orderdate) sorted from business ) t where sorted = 1;
六. Rank
1.函式說明
RANK() 排序相同時會重複,總數不會變
DENSE_RANK() 排序相同時會重複,總數會減少
ROW_NUMBER() 會根據順序計算
2. 案例
計算每門學科成績排名
select name, subject, score, rank() over(partition by subject order by score desc) rk, dense_rank() over(partition by subject order by score desc) drk, row_number() over(partition by subject order by score desc) r_number from score;