全網最全的SQL解析Json總結

2021-02-20 大數據技術與數據開發

一、HiveSQL中的Json解析對於從事數倉開發的同學Json解析是進行數倉開發中很很常會遇到的問題。相對於後端開發,提供了很多好用的Json解析工具包而言,SQL在json解析方面還是偏弱。而且有些解析語法如果不是經常用,其實也很容易遺忘。我大概總結了常用的SQL解析的三大分類,分別是直譯型行轉列型正則型二、直譯型

所謂直譯型,就是不用廢腦子的。傻瓜化函數解析,包括get_json_object、json_tuple.

2.1 get_json_object

•語法: get_json_object(json, args)

            •對於json中的key.直接用'$.key'標識            •對於json中的數組.用'$.key[0]'標識取key這個數組索引為0的值.如果本身就是一個json數組,那麼使用'$.[0]'標識取第一個元素.
select get_json_object('{"user_name":"suweipeng"}', '$.user_name');

select get_json_object('{"user_name":"suweipeng", "addrs":["北京","杭州","成都"]}', '$.addrs[0]');

2.2 json_tuplejson_tuple和get_json_object的關鍵區別在於其解析參數是可變參數。即可以接多個需要解析的json欄位,一次性解析出來。適用於需要一次性解析一個json中的多個欄位。其次json_tuple不用使用$標識要提取的欄位.

•語法: json_tuple(json, args...)•例子:

select json_tuple('{"user_name":"suweipeng", "company":"didi", "phone_number":18699999999}', 'user_name', 'company', 'phone_number');

三、行轉列型•很多時候, 我們會碰到遇到這種需求,由於後端開發表結構的設計原因,將一對多的關係直接塞進了json中。比如後端用user_id和addrs這兩個欄位,表示一個用戶對應的可能住址。其中addrs欄位的key為省份,value為具體城市。但是這樣的設計對於數倉開發不好用於分析。•PS: 我把一行轉成多列稱為行轉列,不同於網上定義的行轉列。user_idaddrs123456789[{"city":"福州"}, {"city":"北京"}]

我們希望將其轉換成如下表結構

user_idcity123456789福州123456789北京

對於這種類型的需求,我們就需要藉助lateral view語法.

3.1 json_split和lateral view的配合

•先用json_split將json字符串轉換成hive數組.•然後用explode將數組炸開.•lateral view可以理解為sql中的for循環寫法

那麼下面的sql就很指標了,將json數組轉換成Hive數組中後,一個個拿出來,再調用get_json_object解析.即可實現一行轉多列效果。
with tbl as (     select          '123456789' as user_id         ,'[{"city":"福州"}, {"city":"北京"}]' as addrs)select     user_id    ,get_json_object(json,'$.city') as cityfrom (select     user_id    ,json_split(addrs) json_arrfrom tbl) tlateral view explode(json_arr) jsons as json;

結果如下圖

3.2 json_tuple和lateral view的配合user_idaddrs123456789[{"city":"福州", "area":"鼓樓區"}, {"city":"北京": "area":"朝陽區"}]

既然lateral view等效於for循環.那麼later view就是可以嵌套的.所以對於上述addrs的解析.我們可以

•先使用一個for循環取出一個個的json.•再使用一個for循環藉助json_tuple函數解析出所有欄位.這是json_tuple經常會結合lateral view使用,因為這樣就可以json_tuple解析出的表,給予列名。

with tbl as (     select          '123456789' as user_id         ,'[{"city":"福州", "area":"鼓樓區"}, {"city":"北京","area":"朝陽區"}]' as addrs)select     user_id    ,city    ,areafrom (select     user_id    ,json_split(addrs) json_arrfrom tbl) tlateral view explode(json_arr) jsons as jsonlateral view json_tuple(json,'city', 'area') resultTbl as city, area;

3.3 出個難題user_idaddrs123456789[{"福建":"福州"}, {"北京":"北京"}]

將如上數據,用SQL轉換成如下表.

user_idprovincecity123456789福建福州123456789北京北京四、正則型基本上掌握了get_json_object和json_tuple還有lateral view配合其他循環函數的使用.能夠勝任99%的json解析工作。但是實際工作中會遇到一些比較變態的解析.格式可能並非json格式, 還需要進行解析,這時候只能用正則表達式來強行提取了。4.1 regexp_replace

語法: regexp_replace(json, 正則表達式, 替換值)

例子:

去掉所有中括號

select regexp_replace('[{"key1":"value1"},{"key2":"value2"}]','\\[|\\]','');

4.2 regexp_extract

語法: regexp_extract(json, 正則表達式, 分組索引).

•通常會結合()進行分組, 從1開始計數.•所以分組索引為1,表示取第一個()分組的值.•分組索引為0, 表示取整個字符串.

例子:

只去掉首末中擴號

•匹配以[開頭, ]結尾。並且中間至少有一個字符的字符串.•其中1表示取出中間那個字符串.

select regexp_extract('[{"key1":"value1"},{"key2":"value2"}]','^\\[(.+)\\]$',1)

結合正則-解決 3.3的難題

with tbl as (     select          '123456789' as user_id         ,'[{"福建":"福州"}, {"北京":"北京"}]' as addrs)select     user_id    ,regexp_extract(json,'^\\{\\"(.+)\\":\\"(.+)\\"\\}$', 1)  as province    ,regexp_extract(json,'^\\{\\"(.+)\\":\\"(.+)\\"\\}$', 2)  as cityfrom (select     user_id    ,json_split(addrs) json_arrfrom tbl) tlateral view explode(json_arr) jsons as json;

4.3 split

語法: split(str, 分割符)

•split函數經常結合explode爆炸函數使用, 因為split完後就是一個hive數組.•並且split的分割符,支持根據正則表達式進行分割.

五、總結

•通常的json解析,藉助上面的介紹的三種類型相互組合,可以解決99.99%的問題。•更複雜的json,如果用上述解析很麻煩,可以考慮寫UDF,用Java的方式解析json。這也是最容易,也是最麻煩的方式。最容易的方式在於用Java來解析json十分簡單,最麻煩的是還要進行打包,編譯,上傳到HDFS,進行函數註冊等。

相關焦點

  • 阿里P8深夜總結!如何再Apache Hive中解析 Json數組
    如何在 Apache Hive 中解析 Json 數組Hive 內部提供了大量的內置函數用於處理各種類型的需求。從內置的 UDF 可以看到兩個用於解析 Json的函數:get_json_object 和 json_tuple。
  • 嘗試一下sql server2016裡面的json功能
    另外一個東西,sql server 2016能支持json 的解析和應用啦,雖然我不知道它的性能如何,先來一發測試一下功能 測試一下基本的,從查詢結果裡面構造一個json 的格式create table t1(ID int identity,name nvarchar(50),Chinese int ,Math int)insert into t1 values
  • hive sql 優化心得
    :select uid,uname,sexfrom user_infowhere dt >= '20190201'and dt <= '20190224'and age = 18;當列很多或者數據量很大時,如果select * 或者不指定分區,全列掃描和全表掃描效率都很低
  • php讀取資料庫數據,並以json格式返回數據
    $conn) { die('連接失敗: ' . mysqli_error($conn)); }第二步查詢資料庫$json = '';$data = array(); $sql = "SELECT * FROM paging";//sql查詢語句 $result = mysqli_query($conn,$sql);第三步獲取查詢數據if($result){
  • php解析json格式的文本
    昨天,在我校的高級培訓群裡,有同學諮詢了如何用php解析json格式的文本問題,老師發現這個問題比較典型,在此將相關的知識點總結分享給同學們,希望對其他同學掌握該知識點也能起到一些幫助。同學jsoly提問說,有這樣的一個數組$arr(如下圖所示)想轉換為php的數組,該如何處理。一眼望去就是個json格式的字符串,顯然php裡面不能這樣定義,這樣的定義會報語法錯誤,就像這樣:該同學認為用json格式存儲數據比較簡潔,問直接用json格式定義一個數組該怎麼做。
  • Flink 全網最全資源(視頻、博客、PPT、入門、實戰、源碼解析、問答等持續更新)
    13、Flink 源碼解析 —— JobManager 處理 SubmitJob 的過程14、Flink 源碼解析 —— TaskManager 處理 SubmitJob 的過程15、Flink 源碼解析 —— 深度解析 Flink Checkpoint 機制16、Flink 源碼解析 —— 深度解析 Flink 序列化機制17、
  • Spark SQL重點知識總結
    Spark SQL客戶端查詢:1、可以通過Spark-shell來操作Spark SQL,spark作為SparkSession的變量名,sc作為SparkContext的變量名2、可以通過Spark提供的方法讀取json文件,將json文件轉換成DataFrame3、可以通過DataFrame提供的API來操作DataFrame
  • 史上最全網絡安全面試題總結
    防禦:基於作業系統防禦 緩衝區邊界檢查 安全編程網絡安全事件應急響應斷網:條件允許時優先斷網,防止黑客進一步操作或刪除痕跡 取證:通過分析登錄日誌、網站日誌、服務日誌尋找黑客ip,查看黑客進行的操作 備份:備份伺服器文件,對比入侵前後產生變化的文件 查漏:通過上述步驟尋找業務薄弱點,修補漏洞
  • 大數據分析工程師入門9-Spark SQL
    >2)解析分區信息parquet文件中如果帶有分區信息,那麼SparkSQL會自動解析分區信息。:string(nullable=true)目前自動解析分區支持數值類型和字符串類型。自動解析分區類型的參數為:spark.sql.sources.partitionColumnTypeInference.enabled,默認值為true。可以關閉該功能,直接將該參數設置為disabled。此時,分區列數據格式將被默認設置為string類型,不會再進行類型解析。
  • flink sql 知其所以然(一)| source\sink 原理
    先聊聊使用 sql 的原因,總結來說就是一切從簡。目前 1.13 版本的 SQL 已經集成了大量高效、易用的 feature。本系列教程也是基於 1.13.1。3.定義篇-sql source、sink本文會簡單介紹一些 flink sql 的 source、sink 的定義、使用方法,會著重切介紹其對應框架設計和實現。詳細解析一下從一條 create table sql 到具體的算子層面的整個流程。
  • 使用JSONObject生成和解析json
    構建json在eclipse中使用JSONObject需要引用org.json包,推薦通過maven引用,如果不會使用maven,搭建maven項目可參考這篇文章《使用Eclipse構建Maven項目 (step-by-step)》,引用json則參考這篇文章《maven引入json各種版本》。
  • xml及json解析
    6.設置屬性的文字   Attribute attribute=root.attribute("name");   attribute.setText("sitinspring");將文檔寫入XML1.文檔中全為英文
  • python解析json方法
    易於人閱讀和編寫,同時也易於機器解析和生成。它的格式一般是這樣的:對象是一個無序的「『名稱/值'對」集合。一個對象以「{」(左括號)開始,「}」(右括號)結束。每個「名稱」後跟一個「:」(冒號);「『名稱/值' 對」之間使用「,」(逗號)分隔。
  • jq:命令行下解析JSON的神器
    我們都知道現在JSON是最常用的配置和數據交換格式之一,尤其是大量的系統API接口現在基本上都是以JSON格式顯示結果。JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。
  • Java解析json的一些操作
    >json字符串—>json對象JSON.parseObject() 從字符串解析 JSON 對象JSON.parseArray() 從字符串解析 JSON 數組靜態方法parseObject() 能夠將json格式的字符串轉換成一個JSONObject對象,然後再進行json的「增刪改查」的操作增.put("key","value"
  • 詭異 | Spark使用get_json_object函數
    一、問題現象:使用spark sql調用get_json_object函數後,報如下錯誤:yarn 容器被
  • Mybatis解析動態sql原理分析
    解析各個xml文件。4 XMLScriptBuilder解析xml中各個節點sql部分的Builder。LanguageDriver接口及其實現類(屬性,方法省略了,大家有興趣的自己看),該接口主要的作用就是構造sql:
  • 使用Python讀取,寫入和解析JSON
    JSON是用於數據交換的輕量級數據格式,可以很容易地被人類讀取和寫入,也可以由機器輕鬆解析和生成。它是一種完全獨立於語言的文本格式。
  • spark結構化數據處理:Spark SQL、DataFrame和Dataset
    如下代碼從JSON文件(該文件可以從Spark發行包中找到)創建出一個DataFrame:val df = sqlContext.read.json("examples/src/main/resources/people.json")DataFrame提供了一個領域特定語言(DSL)以方便操作結構化數據。
  • python如何編碼解碼解析json對象
    前言json是一種以鍵值對形式存在的輕量級的數據結構,和python中的字典類型具有相同的表現結構。使用 JSON 函數需要導入 json 庫:import json。在Java中我們知道json有jsonObject和jsonArray,且可以通過String、map等相互轉換,那麼在python中,json對象是如何來讀取解析的呢?python解析json對象1.json.dumpsjson.dumps用於將 Python 對象編碼成 JSON 字符串。