Hive 熱門數據分析筆試題(乾貨滿滿,持續更新中...)

寫在前面:我是「雲祁」,一枚熱愛技術、會寫詩的大數據開發猿。暱稱來源於王安石詩中一句 [ 雲之祁祁,或雨於淵 ] ,甚是喜歡。


寫博客一方面是對自己學習的一點點總結及記錄,另一方面則是希望能夠幫助更多對大數據感興趣的朋友。如果你也對 數據中臺、數據建模、數據分析以及Flink/Spark/Hadoop/數倉開發 感興趣,可以關注我的動態 https://blog.csdn.net/BeiisBei ,讓我們一起挖掘大數據的價值~


每天都要進步一點點,生命不是要超越別人,而是要超越自己! (ง •_•)ง

一、背景

在用HQL進行數據分析時,我們不僅想要聚集前的數據,又想要聚集後的數據,這時候往往可以想到用窗口函數,具體窗口函數的使用,可以參考的這篇博文 hive 窗口函數總結

幾道開胃菜,每一道筆試題,我都儘可能從多個角度來分析,大家可以參考一下,既可以通過自連接來實現,也可以通過窗口函數來解決,歡迎大家討論 🙆‍♂️:

二、筆試題實戰

Hive 的五個筆試題
【Hive】筆試題 01
【Hive】筆試題 02
【Hive】筆試題 03
【Hive】筆試題 04
【Hive】筆試題 05
【Hive】大廠熱門數據分析題
未持完續…

三、數據分析題(案例)

場景舉例:北京市學生成績分析 💥

成績的數據格式:時間,學校,年紀,姓名,科目,成績

樣例數據如下:

2013,北大,1,裘容絮,語文,97
2013,北大,1,慶眠拔,語文,52
2013,北大,1,烏灑籌,語文,85
2012,清華,0,欽堯,英語,61
2015,北理工,3,冼殿,物理,81
2016,北科,4,況飄索,化學,92
2014,北航,2,孔須,數學,70
2012,清華,0,王脊,英語,59
2014,北航,2,方部盾,數學,49
2014,北航,2,東門雹,數學,77
create table t_score (
time int,
school string,
class int,
name string,
subjects string,
score int
)
row format delimited fields terminated by ',';

load data local inpath "/opt/data/a.csv" into table t_score

在這裏插入圖片描述

問題:

分組 TopN,選出2014年每個學校、每個年級、分數前三的科目

select t.*
	from
(
select
	time,
	school,
	class,
	score,
	row_number() over (partition by school, class, subjects order by score desc) rank_code
from t_score
	where time = "2014"
) t
	where t.rank_code <= 3;

在這裏插入圖片描述
詳解如下:
  row_number函數:row_number() 按指定的列進行分組生成行序列,從 1 開始,如果兩行記錄的分組列相同,則行序列 +1。
  over 函數:是一個窗口函數。
  over (order by score) 按照 score 排序進行累計,order by 是個默認的開窗函數。
  over (partition by class) 按照班級分區。
  over (partition by class order by score) 按照班級分區,並按着分數排序。
  over (order by score range between 2 preceding and 2 following) 窗口範圍爲當前行的數據幅度減2加2後的範圍內的數據求和。

優化:

row_number() over (distribute by school, class, subjects sort by score desc) rank_code

2014年,北航,每個班級,每科的分數,及分數上下浮動 2 分的總和

select time,school, class, subjects, score,
sum(score) over (order by score range between 2 preceding and 2 following) sscore
from t_score
where time = "2014" and school="北航";

over (order by score rows between 2 preceding and 2 following):窗口範圍爲當前行前後各移動2行。

where 與 having:2012年,清華 0 年級,總成績大於 200 分的學生以及學生數

select *,sum(score) as total_score,
count(1) over (partition by school, class) 
from t_score where school="清華" and class = 0 and time=2012
group by school, class, name,time,subjects,score having total_score > 50;

在這裏插入圖片描述
having 是分組(group by)後的篩選條件,分組後的數據組內再篩選,也就是說 HAVING 子句可以讓我們篩選成組後的各組數據。
where 則是在分組,聚合前先篩選記錄。也就是說作用在 GROUP BY 子句和 HAVING 子句前。

四、情景分析題

今年加入進來了 10 個學校,學校數據差異很大計算每個學校的平均分。

該題主要是考察數據傾斜的處理方式。

group by 方式很容易產生數據傾斜 ❗,需要注意一下幾點:

Map 端部分聚合
hive.map.aggr=true(用於設定是否在 map 端進行聚合,默認值爲真,相當於 combine) 
hive.groupby.mapaggr.checkinterval=100000(用於設定 map 端進行聚合操作的條數)

有數據傾斜時進行負載均衡
設定 hive.groupby.skewindata,當選項設定爲 true 是,生成的查詢計劃有兩個 MapReduce 任務。

(先打散數據)
第一個 MapReduce 中,map 的輸出結果集合會隨機分佈到 reduce 中, 每個 reduce 做部分聚合操作,並輸出結果。
這樣處理的結果是,相同的 group by key 有可能分發到不同的 reduce 中,從而達到負載均衡的目的;

第二個 MapReduce 任務再根據預處理的數據結果按照 group by key 分佈到 reduce 中
(這個過程可以保證相同的 group by key 分佈到同一個 reduce 中),最後完成最終的聚合操作。

🚀

假設我創建了一張表,其中包含了 2016 年客戶完成的所有交易的詳細信息:

CREATE TABLE transaction_details 
(cust_id INT, amount FLOAT, month STRING, country STRING) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY,;

現在我插入了 100 萬條數據,我想知道每個月的總收入。

問:如何高效的統計出結果,寫出步驟即可。 (提示:動態分區

1.首先分析這個需求,其實並不難,但是由於題目說了,要高效.而且數據量也不小,直接寫sql查詢估計肯定會掛.
2.分析:
    a.我們可以通過根據每個月對錶進行分區來解決查詢慢的問題。 因此,對於每個月我們將只掃描分區的數據,而不是整個數據集。
    b.但是我們不能直接對現有的非分區表進行分區。所以我們會採取以下步驟來解決這個問題:
    c.創建一個分區表,partitioned_transaction:
        i.create table partitioned_transaction 
        (cust_id int, amount float, country string) partitioned by (month string) 
        row format delimited fields terminated by,;
    d.在 Hive 中啓用動態分區:
        i.SET hive.exec.dynamic.partition=true;
        ii.SET hive.exec.dynamic.partition.mode=nonstrict;
    e.將數據從非分區表導入到新創建的分區表中:
        i.insert overwrite table partitioned_transaction partition (month) select cust_id, amount, country, month from transaction_details;
    f.使用新建的分區表實現需求。

歡迎掃碼關注我的公衆號,在這裏我將專注分享數據倉庫、數據建模與大數據技術的相關內容。

在這裏插入圖片描述

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