Hive筆記之collect_list/collect_set/concat_ws/concat 列轉行函數詳解

Hive筆記之collect_list/collect_set/concat_ws/concat函數(列轉行)

create table t_visit_video (
    username string,
    video_name string
) partitioned by (day string)
row format delimited fields terminated by ',';

vi  /home/hadoop/t_visit_video.txt 

張三,大唐雙龍傳
李四,天下無賊
張三,神探狄仁傑
李四,霸王別姬
李四,霸王別姬
王五,機器人總動員
王五,放牛班的春天
王五,盜夢空間

load data local inpath '/home/hadoop/t_visit_video.txt' into table t_visit_video partition (day='20200508');

hive (felix)> select * from t_visit_video;
OK
張三    大唐雙龍傳      20200508
李四    天下無賊        20200508
張三    神探狄仁傑      20200508
李四    霸王別姬        20200508
李四    霸王別姬        20200508
王五    機器人總動員    20200508
王五    放牛班的春天    20200508
王五    盜夢空間        20200508
Time taken: 1.445 seconds, Fetched: 8 row(s)

按用戶分組,取出每個用戶每天看過的所有視頻的名字:
hive (felix)> select username, collect_list(video_name) from t_visit_video group by username;
張三    ["大唐雙龍傳","神探狄仁傑"]
李四    ["天下無賊","霸王別姬","霸王別姬"]
王五    ["機器人總動員","放牛班的春天","盜夢空間"]
Time taken: 26.414 seconds, Fetched: 3 row(s)

但是上面的查詢結果有點問題,因爲霸王別姬實在太好看了,所以李四這傢伙看了兩遍,這直接就導致得到的觀看過視頻列表有重複的,所以應該增加去重,使用collect_set,其與collect_list的區別就是會去重:
hive (felix)> select username, collect_set(video_name) from t_visit_video group by username;
OK
張三    ["神探狄仁傑","大唐雙龍傳"]
李四    ["霸王別姬","天下無賊"]
王五    ["盜夢空間","放牛班的春天","機器人總動員"]
Time taken: 24.167 seconds, Fetched: 3 row(s)

李四的觀看記錄中霸王別姬只出現了一次,實現了去重效果。

--實現了linux的rownum功能

hive (felix)> select username,video_name,day,row_number() over ()  rn from t_visit_video; 
王五    盜夢空間        20200508        1
王五    放牛班的春天    20200508        2
王五    機器人總動員    20200508        3
李四    霸王別姬        20200508        4
李四    霸王別姬        20200508        5
張三    神探狄仁傑      20200508        6
李四    天下無賊        20200508        7
張三    大唐雙龍傳      20200508        8


突破group by限制
還可以利用collect來突破group by的限制,Hive中在group by查詢的時候要求出現在select後面的列都必須是出現在group by後面的,即select列必須是作爲分組依據的列,但是有的時候我們想根據A進行分組然後隨便取出每個分組中的一個B,代入到這個實驗中就是按照用戶進行分組,然後隨便拿出一個他看過的視頻名稱即可:

hive (felix)> select username, collect_list(video_name)[0] from t_visit_video group by username;
張三    神探狄仁傑
李四    霸王別姬
王五    盜夢空間
Time taken: 23.027 seconds, Fetched: 3 row(s)

video_name不是分組列,依然能夠取出這列中的數據。


concat、concat_ws 函數
1)concat只是將各個字符進行拼接
2)concat_ws是將各個字符串 通過一個指定的拼接符進行拼接,相當於Oracle的wm_concat和listagg 

從數據庫裏取N個字段,然後組合到一起用“,”分割顯示,起初想到用CONCAT()來處理,好是麻煩,沒想到在手冊里居然有提到CONCAT_WS(),非常好用。
它是一個特殊形式的 CONCAT(),第一個參數剩餘參數間的分隔符,分隔符可以是與剩餘參數一樣的字符串,如果分隔符是 NULL,返回值也將爲 NULL,這個函數會跳過分隔符參數後的任何 NULL 和空字符串,分隔符將被加到被連接的字符串之間。
hive (felix)> SELECT CONCAT_WS(",","First name","Second name","Last Name");
OK
First name,Second name,Last Name
Time taken: 0.055 seconds, Fetched: 1 row(s)

hive (felix)> SELECT CONCAT(",","First name","Second name","Last Name");
OK
,First nameSecond nameLast Name
Time taken: 0.044 seconds, Fetched: 1 row(s)

hive (felix)> SELECT CONCAT_WS(",","First name",NULL,"Last Name");
OK
First name,Last Name
Time taken: 0.051 seconds, Fetched: 1 row(s)

 

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