| 部分轉載自 https://www.deeplearn.me/2892.html
一般寫sql經常會遇到行轉列或者列轉行之類的操作,就像concat_ws之類的函數被廣泛的使用,今天這個也是經常要使用的拓展方法。
背景介紹
explode與lateral view在關系型數據庫中本身是不該出現的。
因為他的出現本身就是在操作不滿足第一范式的數據(每個屬性都不可再分)。
本身已經違背了數據庫的設計原理(不論是業務系統還是數據倉庫系統),在面向分析的數據庫 數據倉庫中,發生了改變。
explode函數可以將一個array或者map展開,
其中explode(array)使得結果中將array列表里的每個元素生成一行;
explode(map)使得結果中將map里的每一對元素作為一行,key為一列,value為一列,
一般情況下,直接使用即可,也可以根據需要結合lateral view 使用
explode的使用
001,allen,usa|china|japan,1|3|7
002,kobe,usa|england|japan,2|3|5
create table test_message(id int,name string,location array<string>,city array<int>) row format delimited fields terminated by ","
collection items terminated by '|';
load data local inpath "/root/hivedata/test_message.txt" into table test_message;
查看array的元素
用下標進行尋找,類似於其他編程語言中的數組訪問
```
select location[1] from test_message;
```
使用explode
```
select explode(location) from test_message;
select name,explode(location) from test_message; 報錯
當使用UDTF函數的時候,hive只允許對拆分字段進行訪問的。
```
lateral view(側視圖)
-
lateral view為側視圖,意義是為了配合UDTF來使用,把某一行數據拆分成多行數據。
-
不加lateral view的UDTF只能提取單個字段拆分,並不能塞會原來數據表中。
-
加上lateral view就可以將拆分的單個字段數據與原始表數據關聯上.
在使用lateral view的時候需要指定視圖別名和生成的新列別名
tabelA lateral view UDTF(xxx) 視圖別名(虛擬表名) as a,b,c select subview.* from test_message lateral view explode(location) subview as itcast; subview為視圖別名,lc為指定新列別名 select name,subview.* from test_message lateral view explode(location) subview as lc; lateral view explode 相當於一個拆分location字段的虛表,然后與原表進行關聯.
-
json_tuple()函數也是UDTF函數,因為一個json字符串對應了解析出n個字段.與原表數據關聯的時候需要使用lateral view
select id from table lateral view json_tuple(property,'tag_id','tag_type’);
Lateral View 語法
lateralView: LATERAL VIEW udtf(expression) tableAlias AS columnAlias (',' columnAlias)*
fromClause: FROM baseTable (lateralView)*
描述
橫向視圖與用戶定義的表生成函數(如explode())結合使用。 如內置表生成函數中所述,UDTF為每個輸入行生成零個或多個輸出行。 橫向視圖首先將UDTF應用於基表的每一行,然后將結果輸出行連接到輸入行,以形成具有所提供的表別名的虛擬表。
舉個栗子
下表 pageAds. 它有兩個字段: pageid
(頁碼) and adid_list
(頁面上的adid):
Column name | Column type |
---|---|
pageid | STRING |
adid_list | Array
|
另外一個實例:
pageid | adid_list |
---|---|
front_page | [1, 2, 3] |
contact_page | [3, 4, 5] |
用戶想要統計各個頁面出現的廣告的次數
此時可以使用lateral view 和explode處理adid_list 字段得到如下效果
SELECT pageid, adid
FROM pageAds LATERAL VIEW explode(adid_list) adTable AS adid;
The resulting output will be
pageid (string) adid (int)
“front_page” 1
“front_page” 2
“front_page” 3
“contact_page” 3
“contact_page” 4
“contact_page” 5
因為要統計頻次,所以使用group by聚合操作
SELECT adid, count(1)
FROM pageAds LATERAL VIEW explode(adid_list) adTable AS adid
GROUP BY adid;
int adid | count(1) |
---|---|
1 | 1 |
2 | 1 |
3 | 2 |
4 | 1 |
5 | 1 |
Multiple Lateral Views
FROM子句可以有多個LATERAL VIEW子句。 后續的LATERAL VIEWS可以引用出現在LATERAL VIEW左側的任何表格中的列。
如下所示:
SELECT * FROM exampleTable
LATERAL VIEW explode(col1) myTable1 AS myCol1
LATERAL VIEW explode(myCol1) myTable2 AS myCol2;
上面的示例sql中后面一個直接飲用之前的輸出結果作為輸入,假設有以下數據表:
Array<int> col1 Array<string> col2
[1, 2] [a”, “b”, “c”]
[3, 4] [d”, “e”, “f”]
查詢語句
SELECT myCol1, col2 FROM baseTable
LATERAL VIEW explode(col1) myTable1 AS myCol1;
將會生成:
int mycol1 Array<string> col2
1 [a”, “b”, “c”]
2 [a”, “b”, “c”]
3 [d”, “e”, “f”]
4 [d”, “e”, “f”]
當使用兩次lateral view查詢之后:
SELECT myCol1, myCol2 FROM baseTable
LATERAL VIEW explode(col1) myTable1 AS myCol1
LATERAL VIEW explode(col2) myTable2 AS myCol2;
生成如下的結果:
int myCol1 string myCol2
1 “a”
1 “b”
1 “c”
2 “a”
2 “b”
2 “c”
3 “d”
3 “e”
3 “f”
4 “d”
4 “e”
4 “f”