Hive(三):查詢

一、基本查詢

創建部門表:

hive (default)> create table if not exists dept(
deptno int,
dname string,
loc int
)
row format delimited fields terminated by '\t';

創建員工表:

hive (default)> create table if not exists emp(
empno int,
ename string,
job string,
mgr int,
hiredate string, 
sal double, 
comm double,
deptno int)
row format delimited fields terminated by '\t';

初始化數據:

hive (default)> load data local inpath '/root/datas/dept.txt' into table
dept;
hive (default)> load data local inpath '/root/datas/emp.txt' into table emp;

全表查詢: hive (default)> select * from emp;

選擇特定列查詢: hive (default)> select empno, ename from emp;

列別名hive (default)> select ename AS name, deptno dn from emp;

常用函數: count()max()min()sum()avg()

Limit語句hive (default)> select * from emp limit 5;

Where語句: hive (default)> select * from emp where sal >1000;
注意:where子句中不能使用字段別名。

like和rlike:使用LIKE運算選擇類似的值,%代表零個或多個字符(任意個字符),_代表一個字符。RLIKE子句是Hive中這個功能的一個擴展,其可以通過Java的正則表達式這個更強大的語言來指定匹配條件。
hive (default)> select * from emp where sal LIKE '2%';

Group By語句GROUP BY語句通常會和聚合函數一起使用,按照一個或者多個列隊結果進行分組,然後對每個組執行聚合操作。
hive (default)> select t.deptno, avg(t.sal) avg_sal from emp t group by t.deptno;

Having語句: 對分組內做條件約束
hive (default)>select deptno, avg(sal) avg_sal from emp group by deptno having avg_sal > 2000;

注意:連接謂詞中不支持or

二、Join語句

Hive支持通常的SQL JOIN語句,但是隻支持等值連接,不支持非等值連接。

內連接

只有進行連接的兩個表中都存在與連接條件相匹配的數據纔會被保留下來。

hive (default)> select e.empno, e.ename, d.deptno from emp e join dept d on e.deptno = d.deptno;

左外連接
JOIN操作符左邊表中符合WHERE子句的所有記錄將會被返回。

hive (default)> select e.empno, e.ename, d.deptno from emp e left join dept d on e.deptno = d.deptno;

右外連接

右外連接:JOIN操作符右邊表中符合WHERE子句的所有記錄將會被返回。

hive (default)> select e.empno, e.ename, d.deptno from emp e right join dept d on e.deptno = d.deptno;

滿外連接

滿外連接:將會返回所有表中符合WHERE語句條件的所有記錄。如果任一表的指定字段沒有符合條件的值的話,那麼就使用NULL值替代。

hive (default)> select e.empno, e.ename, d.deptno from emp e full join dept d on e.deptno = d.deptno;

多表連接

注意:連接n個表,至少需要n-1個連接條件。例如:連接三個表,至少需要兩個連接條件。

hive (default)>SELECT e.ename, d.dname, l.loc_name
FROM   emp e 
JOIN   dept d
ON     d.deptno = e.deptno 
JOIN   location l
ON     d.loc = l.loc;

大多數情況下,Hive會對每對JOIN連接對象啓動一個MapReduce任務。本例中會首先啓動一個MapReduce job對錶e和表d進行連接操作,然後會再啓動一個MapReduce job將第一個MapReduce job的輸出和表l進行連接操作,Hive總是按照從左到右的順序執行的。
當對3個或者更多表進行join連接時,如果每個on子句都使用相同的連接鍵的話,那麼只會產生一個MapReduce job

三、排序

3.1 全局排序(Order By)

Order By:全局排序,只有一個ReducerASC: 升序(默認)DESC: 降序

hive (default)> select * from emp order by sal desc;

3.2 多個列排序

hive (default)> select ename, deptno, sal from emp order by deptno, sal ;

3.3 內部排序(Sort By)

對於大規模的數據集order by的效率非常低。在很多情況下,並不需要全局排序,此時可以使用sort by
Sort by爲每個Reducer產生一個排序文件。每個Reducer內部進行排序,對全局結果集來說不是排序。

hive (default)> set mapreduce.job.reduces=3;
hive (default)> select * from emp sort by deptno desc;

3.4 分區排序(Distribute By)

在有些情況下,我們需要控制某個特定行應該到哪個Reducer,通常是爲了進行後續的聚集操作。Distribute by子句可以做這件事。Distribute by類似MRPartition(自定義分區)進行分區,結合Sort by使用。

hive (default)> set mapreduce.job.reduces=3;
hive (default)> select * from emp distribute by deptno sort by empno desc;

注意:
1.Distribute by的分區規則是根據分區字段的Hash碼與Reduce的個數進行模除後,餘數相同的分到一個區。
2.Hive要求Distribute by語句要寫在Sort by語句之前。

3.5 Cluster By

Distribute bySorts by字段相同時,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外還兼具Sort by的功能。但是排序只能是升序排序,不能指定排序規則爲ASC或者DESC

hive (default)> select * from emp cluster by deptno;

四、分桶及抽樣查詢

4.1 分桶表數據存儲

分區提供一個隔離數據和優化查詢的便利方式。不過,並非所有的數據集都可形成合理的分區。對於一張表或者分區,Hive可以進一步組織成桶,也就是更爲細粒度的數據範圍劃分。分桶是將數據集分解成更容易管理的若干部分的另一個技術。

分區針對的是數據的存儲路徑;分桶針對的是數據文件。

設置分桶屬性:hive (default)> set hive.enforce.bucketing=true;

創建分桶表時,數據只能通過子查詢的方式導入

創建普通表stu

hive (default)> create table stu(id int, name string)
row format delimited fields terminated by '\t';

創建分桶表stu_buck

hive (default)> create table stu_buck(id int, name string)
clustered by(id) 
into 4 buckets
row format delimited fields terminated by '\t';

向普通表stu導入數據:load data local inpath '/root/datas/student.txt' into table stu;

通過子查詢的方式導入數據到分桶表:insert into table stu_buck select id, name from stu;

在這裏插入圖片描述
Hive的分桶採用對分桶字段的值進行哈希,然後除以桶的個數求餘的方式決定該條記錄存放在哪個桶當中。

4.2 分桶抽樣查詢

對於非常大的數據集,有時用戶需要使用的是一個具有代表性的查詢結果而不是全部結果。Hive可以通過對錶進行抽樣來滿足這個需求。

查詢表stu_buck中的數據:hive (default)> select * from stu_buck tablesample(bucket 1 out of 4 on id);

注:tablesample是抽樣語句,語法:TABLESAMPLE(BUCKET x OUT OF y)

y必須是tablebucket數的倍數或者因子。Hive根據y的大小,決定抽樣的比例。例如,table總共分了4份,當y=2時,抽取(4/2=)2個bucket的數據,當y=8時,抽取(4/8=)1/2個bucket的數據。

x表示從哪個bucket開始抽取,如果需要取多個分區,以後的分區號爲當前分區號加上y。例如,tablebucket數爲4,tablesample(bucket 1 out of 2),表示總共抽取(4/2=)2個bucket的數據,抽取第1(x)個和第3(x+y)個bucket的數據。

注意:x的值必須小於等於y的值。

五、常用查詢函數

5.1 空字段賦值

NVL函數:給值爲NULL的數據賦值,它的格式是NVL( value,default_value)。它的功能是如果valueNULL,則NVL函數返回default_value的值,否則返回value的值。

hive (default)> select emp,nvl(comm, 0) from emp;

5.2 CASE WHEN

需求:求出不同部門男女各多少人

數據準備:

[hucheng@hadoop100 datas]$ vi emp_sex.txt
悟空	A	男
大海	A	男
宋宋	B	男
鳳姐	A	女
婷姐	B	女
婷婷	B	女

創建Hive表並導入數據

hive (default)> create table emp_sex(name string, dept_id string, sex string) 
row format delimited fields terminated by "\t";

hive (default)> load data local inpath '/root/datas/emp_sex.txt' into table emp_sex;

按需求查詢數據:

hive (default)> select 
  dept_id,
  sum(case sex when '男' then 1 else 0 end) male_count,
  sum(case sex when '女' then 1 else 0 end) female_count
from emp_sex
group by dept_id;

5.3 行轉列

CONCAT(str1,str2…):返回輸入字符串連接後的結果,支持任意個輸入字符串;

CONCAT_WS(separator, str1, str2,…):它是一個特殊形式的CONCAT()。第一個參數剩餘參數間的分隔符。分隔符可以是與剩餘參數一樣的字符串。如果分隔符是NULL,返回值也將爲NULL。這個函數會跳過分隔符參數後的任何NULL和空字符串。分隔符將被加到被連接的字符串之間;

COLLECT_SET(col):函數只接受基本數據類型,它的主要作用是將某字段的值進行去重彙總,產生Array類型字段。

數據準備:

[root@hadoop100 datas]$ vi constellation.txt
孫悟空	白羊座	A
大海	     射手座	A
宋宋	     白羊座	B
豬八戒    白羊座	A
鳳姐	     射手座	A

需求:把星座和血型一樣的人歸類到一起,結果如下:

射手座,A            大海|鳳姐
白羊座,A            孫悟空|豬八戒
白羊座,B            宋宋

創建Hive表並導入數據

hive (default)> create table person_info(name string, constellation string, 
blood_type string) 
row format delimited fields terminated by "\t";

hive (default)>load data local inpath "/root/datas/constellation.txt" into table person_info;

按需求查詢:

hive (default)> select concat_ws("|",collect_set(name)) all_name, base from  
(select name,concat(constellation,",",blood_type) base from person_info) t
group by base ;

5.4 列轉行

EXPLODE(col):將Hive一列中複雜的Array或者Map結構拆分成多行。

LATERAL VIEW
用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias
解釋:用於和SplitexplodeUDTF一起使用,它能夠將一列數據拆成多行數據,在此基礎上可以對拆分後的數據進行聚合。

數據準備:

[root@hadoop100 datas]$ vi movie.txt
《疑犯追蹤》	懸疑,動作,科幻,劇情
《Lie to me》	懸疑,警匪,動作,心理,劇情
《戰狼2》	戰爭,動作,災難

需求:將電影分類中的數組數據展開,結果如下:

《疑犯追蹤》      懸疑
《疑犯追蹤》      動作
《疑犯追蹤》      科幻
《疑犯追蹤》      劇情
《Lie to me》   懸疑
《Lie to me》   警匪
《Lie to me》   動作
《Lie to me》   心理
《Lie to me》   劇情
《戰狼2》        戰爭
《戰狼2》        動作
《戰狼2》        災難

創建Hive表並導入數據:

hive (default)> create table movie_info(movie string, category array<string>) 
row format delimited fields terminated by "\t"
collection items terminated by ",";

hive (default)> load data local inpath "/root/datas/movie.txt" into table movie_info;

按需求查詢:

hive (default)> select movie,category_name from movie_info 
lateral view explode(category) table_tmp as category_name;

5.5 窗口函數(開窗函數)

OVER():指定分析函數工作的數據窗口大小,這個數據窗口大小可能會隨着行的變而變化。
CURRENT ROW:當前行
n PERCEDING:往前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類型。

數據準備:

[root@hadoop100 datas]$ vim business.txt
jack,2017-01-01,10
tony,2017-01-02,15
jack,2017-02-03,23
tony,2017-01-04,29
jack,2017-01-05,46
jack,2017-04-06,42
tony,2017-01-07,50
jack,2017-01-08,55
mart,2017-04-08,62
mart,2017-04-09,68
neil,2017-05-10,12
mart,2017-04-11,75
neil,2017-06-12,80
mart,2017-04-13,94

創建Hive表並導入數據:

hive (default)> create table business(name string, orderdate string,cost int) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

hive (default)> load data local inpath "/root/datas/business.txt" into table business;

① 查詢在2017年4月份購買過的顧客及總人數

hive (default)> select distinct name,count(*) over() 
from business 
where substring(orderdate,0,7) = '2017-04';

② 查詢顧客的購買明細及月購買總額

hive (default)> select name,orderdate,cost,
sum(cost) over(partition by name,month(orderdate)) 
from business;

③ 上述的場景, 將每個顧客的cost按照日期進行累加

hive (default)> select *,
sum(cost) over(partition by name order by orderdate 
rows between unbounded preceding and current row)
from business;

④ 查詢每個顧客上次的購買時間

hive (default)> select *,lag(orderdate,1,"---")
over(partition by name order by orderdate)
from business;

⑤ 查詢前20%時間的訂單信息

hive (default)> select * from (
    select name,orderdate,cost, ntile(5) over(order by orderdate) sorted
    from business
) t
where sorted = 1;

5.6 Rank

RANK() :排序相同時會重複,總數不會變
DENSE_RANK(): 排序相同時會重複,總數會減少
ROW_NUMBER() :會根據順序計算

數據準備:

[root@hadoop100 datas]$ vim score.txt
孫悟空	語文	87
孫悟空	數學	95
孫悟空	英語	68
大海	語文	94
大海	數學	56
大海	英語	84
宋宋	語文	64
宋宋	數學	86
宋宋	英語	84
婷婷	語文	65
婷婷	數學	85
婷婷	英語	78

創建Hive表並導入數據:

hive (default)> create table score(name string,subject string, score int) 
row format delimited fields terminated by "\t";

hive (default)> load data local inpath '/root/datas/score.txt' into table score;

需求:計算每門學科成績排名

hive (default)> select name,subject,score,
rank() over(partition by subject order by score desc) rp,
dense_rank() over(partition by subject order by score desc) drp,
row_number() over(partition by subject order by score desc) rmp
from score;

在這裏插入圖片描述

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