成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Hive必會SQL語法Explode 和 Lateral View

數據庫 MySQL
在業務系統中是存貯在非關系型數據庫中,用json存儲的概率比較大,直接導入hive為基礎的數倉系統中,就需要經過ETL過程解析這類數據,explode與lateral view在這種場景下大顯身手。

 [[385381]]

本文轉載自微信公眾號「Java大數據與數據倉庫」,作者劉不二。轉載本文請聯系Java大數據與數據倉庫公眾號。  

explode 和 lateral view

為什么把這兩個放一塊呢,因為這兩個經常放在一起用啊

explode與lateral view在關系型數據庫中本身是不該出現的,因為他的出現本身就是在操作不滿足第一范式的數據(每個屬性都不可再分),本身已經違背了數據庫的設計原理(不論是業務系統還是數據倉庫系統),不過大數據技術普及后,很多類似pv,uv的數據,在業務系統中是存貯在非關系型數據庫中,用json存儲的概率比較大,直接導入hive為基礎的數倉系統中,就需要經過ETL過程解析這類數據,explode與lateral view在這種場景下大顯身手。

explode用法

在介紹如何處理之前,我們先來了解下Hive內置的 explode 函數,官方的解釋是:explode() takes in an array (or a map) as an input and outputs the elements of the array (map) as separate rows. UDTFs can be used in the SELECT expression list and as a part of LATERAL VIEW. 意思就是 explode() 接收一個 array 或 map 類型的數據作為輸入,然后將 array 或 map 里面的元素按照每行的形式輸出。其可以配合 LATERAL VIEW 一起使用。光看文字描述很不直觀,咱們來看看幾個例子吧。

  1. hive (default)> select explode(array('A','B','C')); 
  2. OK 
  3. Time taken: 4.188 seconds, Fetched: 3 row(s) 
  4.  
  5. hive (default)> select explode(map('a', 1, 'b', 2, 'c', 3)); 
  6. OK 
  7. key    value 
  8. a    1 
  9. b    2 
  10. c    3  

explode函數接收一個數組或者map類型的數據,通常需要用split函數生成數組。

explode 配合解析Json 數組

這里有數據:

  1. {"info":[ 
  2.     {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  3.     {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  4.     {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  5.     {"AppName":"2345Explorer_embedupdate","plugin":"-1"}, 
  6.     {"AppName":"SogouExplorer_embedupdate","pepper":"-1"
  7. ]} 

現在需要將AppName和pepper提取出來,然后按行存放,一行一個,首先我們按照上一節我們學習的Json 處理的函數進行嘗試

  1. select 
  2. get_json_object( 
  3.   '{"info":[ 
  4.     {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  5.     {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  6.     {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  7.     {"AppName":"2345Explorer_embedupdate","plugin":"-1"}, 
  8.     {"AppName":"SogouExplorer_embedupdate","pepper":"-1"
  9.   ]}', 
  10.   "$.info[*].AppName" 
  11. ); 

如圖

image-20201231111231311

但是我們注意到這里雖然提取出來了但是返回值是一個字符串啊,我為啥知道它是字符串,但是看起來像是一個數組啊,因為我用explode 函數試過了,那接下來怎么處理呢,這個時候就可以需要配合split 處理了,為了方便操作我直接用上么的結果進行操作

  1. ["SogouExplorer_embedupdate","SogouExplorer_embedupdate","SogouExplorer_embedupdate","2345Explorer_embedupdate","SogouExplorer_embedupdate"

然我我們嘗試處理一下上面這個字符串,首先我們需要split 一下,但是在此之前我們需要將兩邊的中括號去掉,否則到時候我們的數據會包含這個兩個符號的

  1. select regexp_replace('["SogouExplorer_embedupdate","SogouExplorer_embedupdate","SogouExplorer_embedupdate","2345Explorer_embedupdate","SogouExplorer_embedupdate"]',"[\\[\\]]",''

然后我們就可以split和explode 的了

  1. select explode(split(regexp_replace('["SogouExplorer_embedupdate","SogouExplorer_embedupdate","SogouExplorer_embedupdate","2345Explorer_embedupdate","SogouExplorer_embedupdate"]',"[\\[\\]]",''),',')); 

image-20201231112616809

這里解析json數組,我們本質上還是使用regexp_replace替換掉中括號,然后再使用split函數拆分為數據,給explode去分裂成多行。上面的這種寫法有問題嗎,功能是可以完成,但是這里只是提出來了AppName 這個字段,還有一個字段沒有提取出來呢,要是想把它提取出來,上面的步驟你還得再來一遍才可以,接下來我們嘗試引入json_tuple來簡化一下我們的操作,我們先將其explode 成多行簡單json 字符串,然后再使用json_tuple 進行處理

  1. select 
  2. explode( 
  3.   split( 
  4.      regexp_replace( 
  5.         regexp_replace( 
  6.           get_json_object( 
  7.             '{"info":[ 
  8.               {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  9.               {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  10.               {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  11.               {"AppName":"2345Explorer_embedupdate","plugin":"-1"}, 
  12.               {"AppName":"SogouExplorer_embedupdate","pepper":"-1"
  13.             ]}',"$.info"
  14.        ,'[\\[\\]]' ,''
  15.      ,'(},\\{)','}#\\{'
  16.     ,'#'
  17.  ); 

這里兩次調用了regexp_replace,第一次是為了去掉兩邊的中括號,第二次是為了將,jons 里面的逗號和分割json 的逗號進行區分,因為我們按照數組內容之間的分隔符進行split ,所以這里可以看做是將數組字符串的分隔符有逗號換成了# 號,然后就按照# split 了

image-20201231122203730

接下來就可以調用json_tuple 函數了

  1. select 
  2.     json_tuple(data,'AppName','pepper'
  3. from
  4.   select 
  5.   explode( 
  6.     split( 
  7.        regexp_replace( 
  8.           regexp_replace( 
  9.             get_json_object( 
  10.               '{"info":[ 
  11.                 {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  12.                 {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  13.                 {"AppName":"SogouExplorer_embedupdate","pepper":"-1"}, 
  14.                 {"AppName":"2345Explorer_embedupdate","plugin":"-1"}, 
  15.                 {"AppName":"SogouExplorer_embedupdate","pepper":"-1"
  16.               ]}',"$.info"
  17.          ,'[\\[\\]]' ,''
  18.        ,'(},\\{)','}#\\{'
  19.       ,'#'
  20.    ) as data 
  21. ) json_table; 

如圖

image-20201231122505355

這樣我們就將我們需要的字段解析出來了

lateral view

開始之前我們先說一下它的用法 LATERAL VIEW udtf(expression) tableAlias AS columnAlias,你可以將lateral view翻譯為側視圖

我們有這樣的一份樣本數據(

  1. 劉德華    演員,導演,制片人 
  2. 李小龍    演員,導演,制片人,幕后,武術指導 
  3. 李連杰    演員,武術指導 
  4. 劉亦菲    演員 

這里我們希望轉換成下面這樣的格式

  1. 劉德華 演員 
  2. 劉德華 導演 
  3. 劉德華 制片人 
  4. 李小龍 演員 
  5. 李小龍 導演 
  6. 李小龍 制片人 
  7. 李小龍 幕后 
  8. 李小龍 武術指導 
  9. create table ods.ods_actor_data( 
  10.     username string, 
  11.     userrole string 
  12. ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
  13. load data local inpath "/Users/liuwenqiang/workspace/hive/lateral.data" overwrite into table ods.ods_actor_data; 

如圖

image-20201231133130769

從我們前面的學習,我們知道這里應該用explode函數

  1. select explode(split(userrole,',')) from  ods.ods_actor_data; 

image-20201231134156444

理論上我們這下只要把username 也選出來就可以了

  1. select username,explode(split(userrole,',')) from  ods.ods_actor_data; 

Error: Error while compiling statement: FAILED: SemanticException [Error 10081]: UDTF's are not supported outside the SELECT clause, nor nested in expressions (state=42000,code=10081)

因為explode 是一個UDTF,所以你不能直接和其他字段一起使用,那應該怎么做呢在

  1. select 
  2.    username,role 
  3. from 
  4.     ods.ods_actor_data 
  5. LATERAL VIEW 
  6.     explode(split(userrole,',')) tmpTable as role 

如圖

image-20201231154758339

看起來到這里我們的實現就結束了

lateral view outer

為什么會多了一個 OUTER 關鍵字呢,其實你也可以猜到了outer join 有點像,就是為了避免explode 函數返回值是null 的時候,影響我們主表的返回,注意是null 而不是空字符串

  1. select 
  2.    username,role 
  3. from 
  4.     ods.ods_actor_data 
  5. LATERAL VIEW 
  6.      explode(array()) tmpTable as role 

如圖

image-20201231160414501

加上outer 關鍵字之后

  1. select 
  2.    username,role 
  3. from 
  4.     ods.ods_actor_data 
  5. LATERAL VIEW outer 
  6.     explode(array()) tmpTable as role 

如圖

image-20201231160459117

其實一個SQL你可以多次使用lateral view也是可以的,就像下面這樣

  1. SELECT * FROM exampleTable 
  2. LATERAL VIEW explode(col1) myTable1 AS myCol1 
  3. LATERAL VIEW explode(myCol1) myTable2 AS myCol2; 

lateral view 的實現原理是什么

首先我們知道explode()是一個UDTF 就是一個輸入進去,多個輸出出來,或者是進去一行,出來一列(多行)

image-20201231162007648

lateral view 關鍵字就是將每一行的特定字段交給explode 函數的表達式,然后將輸出結果和當前行做笛卡爾積,然后重復,直到循環完表里的全部數據,然后就變成下面裝了(圖中省略了傳給explode 字段的那一列)

image-20201231162254979

但其實到這里我就產生了一個疑問,為啥要這樣設計,直接將普通字段和UDTF 的函數的返回值一起查詢不好嗎,然后將原始字段和UDTF 的返回值做笛卡爾積就行了啊,為啥還要lateral view 呢,哈哈。

lateral view 中where 的使用

你可能會說where 不就那么用嗎,還有啥不一樣的,還真有,例如我上面的信息只要劉德華的,那你肯定會寫出下面的SQL

  1. select 
  2.     username,role 
  3. from 
  4.     ods.ods_actor_data 
  5.         LATERAL VIEW 
  6.     explode(split(userrole,',')) tmpTable as role 
  7. where 
  8.     username='劉德華' 

要是我只要導演的呢,但是我們知道userrole 這個字段是包沒有直接是導演的,但是又包含導演的演員,導演,制片人,幕后,武術指導,其實這個時候你可以用下面的別名字段role

  1. select 
  2.     username,role 
  3. from 
  4.     ods.ods_actor_data 
  5.         LATERAL VIEW 
  6.     explode(split(userrole,',')) tmpTable as role 
  7. where 
  8.     role="導演" 

如圖

image-20201231165856030

總結

一個SQL 里lateral view 你可以多次使用,就會多次做笛卡爾積;

UDTF 要配合lateral view 一起使用才可以;

其實回過頭來看的話,我們上面的處理過程就是將一行轉化為多行,典型的行轉列的實現,是SQL 面試的高頻考點;

 

責任編輯:武曉燕 來源: Java大數據與數據倉庫
相關推薦

2017-05-03 09:40:43

HIVEcollectexplode

2023-11-09 14:47:51

SQL工具數據庫

2020-04-15 10:58:10

MySQL數據庫SQL

2010-09-14 16:00:34

sql select語

2010-09-08 17:10:24

SQL循環語句

2010-09-26 10:27:22

SQL替換語句

2011-08-23 13:16:41

SQLEXPLAIN

2010-09-17 10:24:47

SQL中IS NULL

2010-09-24 19:08:08

SQL事務

2009-11-17 13:35:40

Oracle SQL語

2018-11-29 09:01:26

Apache FlinJOIN代碼

2023-03-28 07:36:01

SQL數據庫管理

2010-09-24 17:19:54

SQL中SUBSTRI

2010-11-12 13:40:38

動態sql語句

2010-11-09 10:10:08

SQL Server

2010-09-27 10:59:23

SQL SERVER事

2010-11-11 10:18:59

select into

2024-01-23 18:49:38

SQL聚合函數數據分析

2010-10-19 14:45:01

SQL SERVER臨

2010-11-11 17:20:51

SQL Server創
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美黄色一区 | 国产精品久久久久久52avav | 亚洲高清一区二区三区 | 自拍偷拍视频网 | 欧美精品1区 | 成人免费精品 | 91视频在线看 | 99视频久 | 91视频在线看 | 久久久久亚洲精品 | 国产精品自产拍 | 久久久tv | 日韩av在线一区二区三区 | 一区二区精品在线 | 国产在线观看福利 | 欧美精品一区在线发布 | 人人操日日干 | 亚州中文 | 亚洲一区二区电影网 | 国产乱码久久久久久一区二区 | 欧美日韩精品一区 | 在线观看国产精品视频 | 天堂在线中文 | 99精品久久 | 成人午夜免费网站 | 一区二区三区欧美 | 男人天堂国产 | 免费看片在线播放 | 国产丝袜一区二区三区免费视频 | 毛片一区二区三区 | 天天精品在线 | 成人精品高清 | 91av免费看 | 亚洲 欧美 在线 一区 | 中文字幕免费在线观看 | 美日韩中文字幕 | 亚洲一二三区在线观看 | 欧美国产日韩成人 | 精品美女视频在免费观看 | 亚洲欧美日韩一区二区 | 日韩国产一区二区三区 |