=Start=
缘由:
在用Hive SQL做数据分析的过程中遇到的一个情况,觉得挺典型的,后面可能会遇到,所以记录下来,方便后面参考。
正文:
参考解答:
测试样例
# file_schema (类型1,string类型的列名列表,用方括号包裹起来,不需要额外处理)
["企业号uid","公司名称"]
# file_schema (类型2,string类型字段,json字符串格式,需要将所有的key都提取出来)
{"activity_type":"string","business_tag":"string","activity_tags":"string","campaign_type":"string","tool_name":"string"}
-- 提取结果
# file_columns1
activity_type,business_tag,activity_tags,campaign_type,tool_name
# file_columns2
"activity_type","business_tag","activity_tags","campaign_type","tool_name"
# file_columns3
{"activity_type","business_tag","activity_tags","campaign_type","tool_name"}
# file_columns4
"activity_type","business_tag","activity_tags","campaign_type","tool_name"
-- 提取方法(为了显示清楚使用case-when语法,其实可以用单行的if()函数来达到目标)
file_schema,
case
when file_schema like '{%' then concat_ws(',',map_keys(str_to_map(replace(substr(file_schema,2),'"',''))))
else file_schema
end as file_columns1,
case
when file_schema like '{%' then concat_ws(',',map_keys(str_to_map(substr(file_schema,2))))
else file_schema
end as file_columns2,
case
when file_schema like '{%' then regexp_replace(file_schema,':"(bigint|tinyint|smallint|int|string|varchar|char|float|double|boolean|decimal|timestamp)"','')
else file_schema
end as file_columns3,
regexp_replace(concat_ws(',',map_keys(str_to_map(regexp_replace(file_schema,'\\([a-zA-Z0-9]+,[a-zA-Z0-9]+\\)','')))),'\\{','') AS file_columns4,
str_to_map(字符串参数, 分隔符1, 分隔符2)
使用两个分隔符将文本拆分为键值对。
分隔符1将文本分成K-V对,分隔符2分割每个K-V对。对于分隔符1默认分隔符是 ',',对于分隔符2默认分隔符是 ':'
> select str_to_map("name:zhangsan,age:25") as m1
{"age":"25","name":"zhangsan"}
> desc function str_to_map;
Function: str_to_map
Class: org.apache.spark.sql.catalyst.expressions.StringToMap
Usage: str_to_map(text[, pairDelim[, keyValueDelim]]) - Creates a map after splitting the text into key/value pairs using delimiters. Default delimiters are ',' for `pairDelim` and ':' for `keyValueDelim`. Both `pairDelim` and `keyValueDelim` are treated as regular expressions.
> select cast(str_to_map("A:1,B:1,C:1") as map<string, int>)
-- {'A': 1, 'B': 1, 'C': 1}
相关解释
下载文件列名(file_schema)字段的分析:
- 只有在下载格式为Excel的时候,才会是下面这种格式:
{"column1":"bigint","column2":"int","column3":"double"}
- 其它的情况下,就是单纯的列名格式(已完全满足需求,不用额外处理):
["column1","column2","column3","column4"]
Hive SQL中的一些函数功能、使用场景学习
str_to_map函数的第一个参数字符串是不以括号包裹的,就是单纯的:key1:value1,key2:value2
这种形式。
当前碰到的一个字符串是:{"column1":"double","column2":"int","column3":"double"}
这种形式。
方法一(更直接)
分析了一下,value的取值范围绝大部分是Hive支持的原始数据类型(数值型,Boolean,字符串,时间戳),所以有一种方式就是把这些相对固定(可以枚举出来)的内容进行批量替换,就可以达到我的目标——只保留键名key列表:
if(file_schema like '{%' , regexp_replace(file_schema,':"(bigint|tinyint|smallint|int|string|varchar|char|float|double|boolean|decimal|timestamp)"','') , file_schema) as file_columns
方法二(更通用)
上面这种情况比较特殊——value的取值是可以枚举出来,有相对固定范围的。除此之外,对于value取值无法预估的情况下,可以使用另一个更为通用的方法:
- 在简单把字符串处理之后,用 str_to_map 函数将字符串转换成map类型
- 然后使用 map_keys 函数取出键名key列表
- 再用 concat_ws 将array类型转换成string类型即可
- (可选)使用 replace/regexp_replace 函数对字符串做一些格式化处理
if(file_schema like '{%' , concat_ws(',',map_keys(str_to_map(replace(substr(file_schema,2),'"','')))) , file_schema) as file_columns
参考链接:
Hive Tutorial
https://cwiki.apache.org/confluence/display/Hive/Tutorial
Hive str_to_map函数
https://www.cnblogs.com/kopao/p/13753560.html
大数据之Hive:Hive函数之str_to_map函数
https://blog.csdn.net/weixin_43597208/article/details/117450579
str_to_map returns map. How to make it return map?
https://stackoverflow.com/questions/38537382/str-to-map-returns-mapstring-string-how-to-make-it-return-mapstring-int
str_to_map function
https://docs.databricks.com/en/sql/language-manual/functions/str_to_map.html
Hive 中 map 类型字段的常用方法学习
https://ixyzero.com/blog/archives/5733.html
hive解析不确定key的json,将key和value分别放入两列
https://blog.csdn.net/lz6363/article/details/103910313
Hive 从json中提取出所有key
https://www.cnblogs.com/144823836yj/p/14752548.html
=END=
《“Hive SQL如何从json格式的字符串中提取出所有key字段”》 有 1 条评论
Hive–map/string→json&处理Json数据的函数
https://blog.csdn.net/qq_46893497/article/details/109959763
`
hive中转化json 格式的函数
1. string 类型 json
* named_struct: 生成key和value的struct结构,传递参数为 named_struct(key1,value1,key2,value2, …, keyN,valueN)
* to_json: 将各种复杂结构(例如:LIST,MAP,NAMED_STRUCT 等)转换成json格式
2. map类型 json
* str_to_map 可以先将string切割成map,再转json
* to_json: 将各种复杂结构(例如:LIST,MAP,NAMED_STRUCT 等)转换成json格式
Hive中处理json数据的两种方式
第一种:将json数据作为字符串进行处理
* get_json_object – 一次取一个字段
* json_tuple – 一次取多个字段
第二种:通过专门的解析类直接加载一个json格式的数据到Hive中
`