hive基礎語法三
from --map階段
join --map(有map端join)或者reduce(reduce join)
on
where --map端
group by --reduce階段
having --reduce端
select --reduce端(或者map端)
order by --reduce端
limit --reduce端(或者map端)
基礎數據類型:
支持mysql或者oracle的數據類型。
struct
size只支持map array
arr的函數較爲豐富
結構體和array的區別
數組只能是某一類型的集合
結構體和array的區別:
數組只能是某種類型的元素集合,但是結構體可以任意類型。
arr的函數較爲豐富內部函數,strcut較少些
兩者取值不一樣,arr使用角標取值,而struct使用屬性名取值
hive文件存儲格式包括以下幾類:
1、TEXTFILE
2、SEQUENCEFILE
3、RCFILE
4、ORCFILE(0.11以後出現)
其中TEXTFILE爲默認格式,建表時不指定默認爲這個格式,導入數據時會直接把數據文件拷貝到hdfs上不進行處理;
SEQUENCEFILE,RCFILE,ORCFILE格式的表不能直接從本地文件導入數據,數據要先導入到textfile格式的表中, 然後再從表中用insert導入SequenceFile,RCFile,ORCFile表中。
嵌套數據類型
嵌套??
所有元素分割符自己調(搜:hive的map類型處理)
hive共支持8個層級的分隔符,依次是:
\001,\002,\003,...\008
map嵌套使用
uid uname belong tax addr
1 xdd wuxian:(300,300),gongjijin:1200,1500,shebao:300,
2 lkq wuxian:200,300,gongjijin:1000,1200,shebao:200
create table qt(
id int,
name string,
addr map<string,array<string>>
)
row format delimited fields terminated by '\t'
collection items terminated by ','
map keys terminated by ':'
;
函數
內置函數:
顯示所有函數:
show functions;
查看函數描述:
desc func_name;
模糊查找hive的函數:
show functions like '*concat*';
rand(7) ;隨機
說明:返回一個0到1範圍內的隨機數。如果指定種子seed,則會等到一個穩定的隨機數序列
round(double,n);取多少位小數 四捨五入
split(str,spliter);
substr(str,start,end) 或者 substring()
size(arr/map) length(str)
concat(str,str.....)
concat_ws(分隔符,str,str1.......)
concat_ws(seprater,str,str1..) : 輸入類型一定是字符串或者數組
cast(col as type)
if(condition,true,false)
case col
when value then ...
when value1 then ...
else
...
end
case
when col=value then ...
when col=value1 then ...
else
...
end
if(condition,true,false)
select if(1=2,"男",if(1=3,"妖","女"));
select
id,
if(1=id,"男",if(2=id,"女","妖"))
from u1
;
case col
when value then ...
when value1 then ...
else
...
end
select
id,
(
case id
when 1 then "男"
when 2 then "女"
else
"妖"
end) sl
from u1
;
case
when col=value then ...
when col=value1 then ...
else
...
end
select
id,
(
case
when id=1 then "男"
when id=2 then "女"
else
"妖"
end) sl
from u1
;
is null
is not null
nvl(val,default_value) : val爲空則返回default
from_unixtime():返回unix時間
unix_timestamp;返回時間戳
to_date():
datediff
date_sub
date_add
last_day
next_day
current_date:
current_timestamp:
hour()
week()
mimint()
1.日期比較函數: datediff語法: datediff(string enddate,string startdate)
返回值: int
說明: 返回結束日期減去開始日期的天數。
舉例:
hive> select datediff('2016-12-30','2016-12-29');
1
2.日期增加函數: date_add語法: date_add(string startdate, intdays)
返回值: string
說明: 返回開始日期startdate增加days天后的日期。
舉例:
hive>select date_add('2016-12-29',10);
2017-01-08
3.日期減少函數: date_sub語法: date_sub (string startdate,int days)
返回值: string
說明: 返回開始日期startdate減少days天后的日期。
舉例:
hive>select date_sub('2016-12-29',10);
2016-12-19
4.查詢近30天的數據
select * from table where datediff(current_timestamp,create_time)<=30;
create_time 爲table裏的字段,current_timestamp 返回當前時間 2018-06-01 11:00:00
=====================================================
show functions;
desc func_name;
coalesce(v1,v2,v3....) 返回第一個不爲空的參數
xpath():返回xml nodes
show function like 'concat'
[外鏈圖片轉存失敗(img-juqjeaT6-1568968991249)(D:/新機/千峯筆記/1568173412359.png)]
trim
ltrim
hive> select ltrim(" sdjfk dsfs ""sdfsdf");
OK
sdjfk dsfs sdfsdf
Time taken: 0.149 seconds, Fetched: 1 row(s)
hive> select trim(" sdjfk dsfs ""sdfsdf");
lpad():左補足
lpad():左補足
replace(str,'',''):
substring_index(str,'a',2):指定索引位置
initcap():首字符變大寫
find_in_set():查找是否在set中,費性能
str_to_map():轉map
get_json_object():獲取json對象
Possible choices: _FUNC_(string, string)
regexp_extract(str,reg,2):正則抽取 ()()()
regexp_replace(str,'',''):正則替換
parse_url():解析url
size(a1):
length(str):
map_keys()
map_values()
mv.["k1"]
mv.[0]
mv.k1
initcap()
initcap(str)——返回str,每個單詞的第一個字母都是大寫的,所有其他字母都是小寫的。單詞由空格分隔。
collect_set():
collect_list():
explode
爆炸(a)——將數組a的元素分成多行,或者將映射的元素分成多行和多列
explode(a) - separates the elements of array a into multiple rows, or the elements of a map into multiple rows and columns
cast():
binary():轉換爲二進制
select empno,ename,job,mgr,hiredate,sal, COALESCE(comm, 0),deptno from emp;
窗口函數:
應用場景:
求出分組內的統計、排名、自增
聚合函數和窗口函數的區別:
1集合函數是多行返回一行
2窗口函數可以達到1行返回一行或者多行返回一行
over(partition by a,b)
count(a) over(partition a,b order by a desc)
count(a) over(order by a desc)
窗口:分爲物理窗口
sum() over()
avg() over()
窗口:邏輯窗口
1 23 23
1 35 58
1 12 70
聚合函數和窗口函數區別:
1、聚合函數是一般是多行 返回一行,窗口函數可以達到1行返回一行或者多行返回一行
over(partition by a,b)
count(a) over(partition by a,b order by a desc)
count(a) over(order by a desc)
窗口:物理窗口和邏輯窗口
物理窗口:rows
邏輯窗口:range
語法:
ROWS/range between [CURRENT ROW | UNBOUNDED PRECEDING | [num] PRECEDING] AND [UNBOUNDED FOLLOWING | [num] FOLLOWING| CURRENT ROW]
sum() over():
count() over()
avg() over()
...over()
first_value
last_value
lag
LAG (scalar_expression [,offset] [,default]) OVER ([query_partition_clause] order_by_clause); The LAG function is used to access data from a previous row.
滯後(scalar_expression [,offset] [,default])超過([query_partition_clause] order_by_clause);滯後函數用於訪問前一行中的數據。
lead
LEAD (scalar_expression [,offset] [,default]) OVER ([query_partition_clause] order_by_clause); The LEAD function is used to return data from the next row.
將(scalar_expression [,offset] [,default])連接到([query_partition_clause] order_by_clause);LEAD函數用於從下一行返回數據。
ntile
NTILE(n)
用於將分組數據按照順序切分成n片,返回當前記錄所在的切片值
NTILE不支持ROWS BETWEEN,比如 NTILE(2) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)
如果切片不均勻,默認增加第一個切片的分佈
經常用來取前30% 帶有百分之多少比例的記錄什麼的
-- 1 把記錄按價格順序拆分成10片
drop table if exists test_dp_price_rk;
create table test_dp_price_rk
as
select
id,
price,
NTILE(10) OVER (order by price desc) as rn
from test_dp_price;
-- 2 按片取30%和70%,分別計算平均值
select
new_rn,
max(case when new_rn=1 then 'avg_price_first_30%' when new_rn=2 then 'avg_price_last_70%' end) as avg_price_name,
avg(price) avg_price
from
(
select
id,
price,
rn,
case when rn in (1,2,3) then 1 else 2 end as new_rn
from test_dp_price_rk
)a
group by new_rn;
案例:
create table if not exists win(
name string,
class string,
score int
)
row format delimited fields terminated by ' '
;
load data local inpath '/home/hivedata/win' into table win;
邏輯:
select
name,
class,
score,
sum(score) over(order by score range between 5 preceding and 5 following) mm
from win;
物理:
select
name,
class,
score,
sum(score) over(order by score rows between 2 preceding and 3 following) mm
from win;
每個班前一名和其後一名的分差:
select
name,
class,
score,
(score-lag(score,1) over(partition by class order by score asc)) diff
from win;
每個班前一名和其後一名的分差:
select
name,
class,
score,
(score-lag(score,1) over(partition by class order by score asc)) diff
from win;
第一個和最後一個值:
select
name,
class,
score,
first_value(score) over(partition by class order by score) first,
last_value(score) over(partition by class order by score) last
from win;
[外鏈圖片轉存失敗(img-kmBBz84t-1568968991250)(D:/新機/千峯筆記/1568184125984.png)]
聚合函數
基本聚合:group by
高級聚合 grouping sets、with cube、with
group by :
grouping sets() : 指定分組
with cube: 數據魔方,任意維度的組合查詢
with rollup :
首先,hive一般分爲基本聚合和高級聚合,而基本聚合就是常見的group by,而高級聚合就是grouping sets、with cube、with rollup等。一般group by與hive內置的聚合函數max、min、count、sum、avg等搭配使用。而cube和rollup則更多參考oracle的cube和rollup聚合而來,從hive 0.10.0版本後開始支持。
需求:求每位學員的每次考試的成績與上一次的成績對比
lag(score,2) -- 取出前n行的數據
lead(score,2) -- 取出後n行的數據
select
dt,
name,
score,
lag(score,1) over(distribute by name sort by dt asc) as upscore
from stu_score
;
排名函數
row_number() over()
rank()
dense_rank()
三者區別:
row_number() over() : 排名函數,名次不會重複,適合於生成主鍵或者不併列排名
rank() over() : 排名函數,有並列名次,名次不連續。如:1,1,3
dense_rank() over() : 排名函數,有並列名次,名次連續。如:1,1,2
案例:
根據class分組,並根據score排名:
select
class,
name,
score,
row_number() over(distribute by class sort by score desc) rn,
rank() over(distribute by class sort by score desc) rk,
dense_rank() over(distribute by class sort by score desc) drk
from win
;
計算每一個班級的前2名:
select
tmp.*
from (
select
class,
name,
score,
row_number() over(distribute by class sort by score desc) rn,
rank() over(distribute by class sort by score desc) rk,
dense_rank() over(distribute by class sort by score desc) drk
from win) tmp
where tmp.rn < 3
;
groupby
分組的意思,使用GROUP BY時,除聚合函數外其他已選擇列必須包含在GROUP BY子句中,否則會報錯。
求某天、某公司、某部門的員工數量:
select
class,
score,
count(*)
from win
group by class,score
;
結果:
1 80 1
1 95 2
2 74 1
2 92 1
3 45 1
3 55 1
3 78 1
3 99 2
select empno,ename,job,mgr,hiredate,sal, COALESCE(comm, 0),deptno from emp;
注意:
1、有group by時,查詢字段要麼在group by子句中,要麼在聚合函數中。
2、group by與聚合函數搭配使用,但是聚合函數不能嵌套使用,如sum(count(*))。
3、如果group by的列值中有null,則包含該null的行將在聚合時被忽略。爲了避免這種情況,可以使用COALESCE來將null替換爲一個默認值。
4、group by與聚合函數count()搭配使用時,同時COUNT又和DISTINCT搭配使用時,Hive將忽略對reducer個數的設置(如:set mapred.reduce.tasks=20;), 僅會有一個reducer!!!此時reduce將成爲瓶頸,這時我們可以使用子查詢的方式解決該問題,同時子查詢需要別名。
5、collect_set() 和collect_list() 不是聚合函數,不需要和group by搭配使用
grouping sets
grouping sets可以實現對同一個數據集的多重group by操作。事實上grouping sets是多個group by進行union all操作的結合,它僅使用一個stage完成這些操作。grouping sets的子句中如果包換()數據集,則表示整體聚合。多用於指定的組合查詢。
例:
1、grouping sets(a,b) ==> group by a union all group by b
2、grouping sets(a,b,(a,b) ==> group by a union all group by b union all group by a,b
3、grouping sets(a,b,(a,b),()) ==>group by a union all group by b union all group by a,b union all 無group by語句
group by class
group by score
group by class,score
例1、
select
class,
NULL as score,
count(*)
from win
group by class
union all
select
NULL AS class,
score,
count(*)
from win
group by score
union all
select
class,
score,
count(*)
from win
group by class,score
;
==如上的語句等價於如下的語句
select
class,
score,
count(*)
from win
group by class,score
grouping sets(class,score,(class,score))
;
上面兩個語句的結果都如下:
NULL 45 1
NULL 55 1
NULL 74 1
NULL 78 1
NULL 80 1
NULL 92 1
NULL 95 2
NULL 99 2
1 NULL 3
2 NULL 2
3 NULL 5
1 80 1
1 95 2
2 74 1
2 92 1
3 45 1
3 55 1
3 78 1
3 99 2
cube
數據立方,
cube俗稱是數據立方,它可以時限hive任意維度的組合查詢。即使用with cube語句時,可對group by後的維度做任意組合查詢,如:group a,b,c with cube ,則它首先group a,b,c 然後依次group by a,c 、 group by b,c、group by a,b 、group a 、group b、group by c、group by () 等這8種組合查詢,所以一般cube個數=2^3個。2是定值,3是維度的個數。多用於無級聯關係的任意組合查詢。
例1、
select
class,
score,
count(*)
from win
group by class,score
with cube
;
==如上語句等價於如下
select
class,
score,
count(*)
from win
group by class,score
grouping sets(class,score,(class,score),())
;
結果如下:
NULL NULL 10
NULL 45 1
NULL 55 1
NULL 74 1
NULL 78 1
NULL 80 1
NULL 92 1
NULL 95 2
NULL 99 2
1 NULL 3
1 80 1
1 95 2
2 NULL 2
2 74 1
2 92 1
3 NULL 5
3 45 1
3 55 1
3 78 1
3 99 2
注意:
如上的實現,如果採用傳統的group by加union all的方式實現,那就是寫得更復雜,大家可以嘗試寫一寫。
rollup
捲起的意思,俗稱層級聚合,相對於grouping sets能指定多少種聚合,而with rollup則表示從左往右的逐級遞減聚合,如:group by a,b,c with rollup 等價於 group by a, b, c grouping sets( (a, b, c), (a, b), (a), ( )).直到逐級遞減爲()爲止,多適用於有級聯關係的組合查詢,如國家、省、市級聯組合查詢。
例1、
select
class,
score,
count(*)
from win
group by class,score
with rollup
;
==上面語句等價於如下語句
select
class,
score,
count(*)
from win
group by class,score
grouping sets((class,score),class,())
;
結果如下:
NULL NULL 10
1 NULL 3
1 80 1
1 95 2
2 NULL 2
2 74 1
2 92 1
3 NULL 5
3 45 1
3 55 1
3 78 1
3 99 2
注意:
如上的實現,也可以採用傳統的group by加union all來實現,大家可以嘗試。
聚合優化
hive.map.agg=true; #最好將其設置爲true,因爲會用到ma端聚合。
hive.new.job.grouping.set.cardinality=30; #在grouping sets/cube/rollup中是否啓用新的job來執行,主要是因爲如果分組多而造成數據立方體炸裂,適當設置該閥值,默認爲30.
自定義函數
自定義函數:
hive的內置函數滿足不了所有的業務需求。
hive提供很多的模塊可以自定義功能,比如:自定義函數、serde、輸入輸出格式等。
常見的自定義函數:
udf:用戶自定義函數,user defined function。一對一的輸入輸出。(最常用的)。
udaf:用戶自定義聚合函數。user defined aggregate function。多對一的輸入輸出。
udtf:用戶自定義表生成函數。user defined table-generate function.一對多的輸入輸出。
常見的自定義函數
udf:一對一的輸入輸出(常用)
udaf:多對一的輸入輸出
udtf:一對多的輸入輸出
編寫:
1、繼承UDF,重寫evaluate(),允許重載。(常用)
2、繼承genericUDF,重寫initlizer()、getdisplay()、evaluate()。
案例:
> add jar /home/hadoop_learn-1.0.jar;
> create temporary function my_concat as 'com.ali.udf.FirstUdf';
> show functions like *my_c*;
hive> show functions like '*my_c*';
OK
my_concat
> select my_concat('a','b');
> select my_concat(class,name),score from win;
永久:
> create function my_concat as 'com.ali.udf.FirstUdf' using jar hdfs://hadoop01:9000/hadoop_learn-1.0.jar;
將udf的包上傳到指定位置。
以後每次將會加載方法。
注意,該方式將會使用庫名.函數名。
CREATE TABLE test (
id string,
hivearray array<binary>,
hivemap map<string,int>)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe'
WITH SERDEPROPERTIES ("field.delim"="[,]","collection.delim"=":","mapkey.delim"="@");
添加函數
法一:
> add jar /home/hadoop_learn-1.0.jar;
> create temporary function my_concat as 'com.ali.udf.FirstUdf';
> show functions like *my_c*;
hive> show functions like '*my_c*';
OK
my_concat
> select my_concat('a','b');
> select my_concat(class,name),score from win;
法二:(永久)
> create function my_concat as 'Udf.DateYear' using jar 'hdfs://hadoop-01:9000/math/my_datayear.jar';
將udf的包上傳到指定位置。
以後每次將會加載方法。
注意,該方式將會使用庫名.函數名。
法三:
將如下兩行語句放到hive的根目錄的bin目錄下的hive-init
add jar /home/hadoop_learn-1.0.jar;
create temporary function my_concat as 'com.ali.udf.FirstUdf';
每次連接就需要使用hive -i ./hive-init
法四:
將如下兩行語句放到hive的根目錄的bin目錄下的.hiverc
add jar /home/hadoop_learn-1.0.jar;
create temporary function my_concat as 'com.ali.udf.FirstUdf';
每次連接就需要使用hive
法五:源碼編譯
法一:
> add jar /home/hadoop_learn-1.0.jar;
> create temporary function my_concat as 'com.ali.udf.FirstUdf';
> show functions like *my_c*;
hive> show functions like '*my_c*';
OK
my_concat
> select my_concat('a','b');
> select my_concat(class,name),score from win;
法二:(永久)
> create function my_concat as 'Udf.DateYear' using jar 'hdfs://hadoop-01:9000/math/my_datayear.jar';
將udf的包上傳到指定位置。
以後每次將會加載方法。
注意,該方式將會使用庫名.函數名。
法三:
將如下兩行語句放到hive的根目錄的bin目錄下的hive-init
add jar /home/hadoop_learn-1.0.jar;
create temporary function my_concat as 'com.ali.udf.FirstUdf';
每次連接就需要使用hive -i ./hive-init
法四:
將如下兩行語句放到hive的根目錄的bin目錄下的.hiverc
add jar /home/hadoop_learn-1.0.jar;
create temporary function my_concat as 'com.ali.udf.FirstUdf';
每次連接就需要使用hive
法五:源碼編譯