SQL进阶:如何把字段中的键值对转为JSON格式?

JSON

一、问题描述

假如某张表的某列是键值对数据,如何把这个键值对转为json格式,数据如下所示

dynasty value
唐朝 唐太宗:李世民;唐高宗:李治;唐玄宗:李隆基;...
汉朝 汉高祖:刘邦;汉文帝:刘恒;汉景帝:刘启;汉武帝:'刘彻';...

需要转成下面这种格式

dynasty value
唐朝 [{"key":"唐太宗","value":"李世民","order":"1"},{"key":"唐高宗","value":"李治","order":"2"},{"key":"唐玄宗","value":"李隆基","order":"3"}...]
汉朝 [{"key":"汉高祖","value":"刘邦","order":"1"},{"key":"汉文帝","value":"刘恒","order":"2"},{"key":"汉景帝","value":"刘启","order":"3"},{"key":"汉武帝","value":"刘彻","order":"2"}...]

二、ORACLE

<一>、键值对拆分(REGEXP_SUBSTR)

sql 复制代码
with split_data as (
	select 
			dynasty,
	 		regexp_substr(value,'[^;]+',1,level) as part,
			level as part_num
	 from table
  connect by 
  	regexp_substr(value,'[^;]+',1,level) is not null
)
	select dynasty,
	       part_num,
	       regexp_substr(part,'[^;]+',1,1) as key,
	       regexp_substr(part,'[^;]+',1,2) as value
      from split_data

执行完就是如下形式

dynasty part_num key value
唐朝 1 唐太宗 李世民
唐朝 2 唐高宗 李治
唐朝 3 唐玄宗 李隆基
汉朝 1 汉高祖 刘邦
汉朝 2 汉文帝 刘恒
汉朝 3 汉景帝 刘启
汉朝 4 汉武帝 刘彻
...

<二>、转为JSON

转为JSON有现成的转JSON函数,完整代码如下

sql 复制代码
with split_data as (
	select 
	        dynasty,
	 		regexp_substr(value,'[^;]+',1,level) as part,
			level as part_num
	 from table
  connect by 
  	regexp_substr(value,'[^;]+',1,level) is not null
),key_value_pairs as (
	select dynasty,
	       part_num,
	       regexp_substr(part,'[^;]+',1,1) as key,
	       regexp_substr(part,'[^;]+',1,2) as value
      from split_data
)
	select dynasty,
	       json_arrayagg(
				josn_object(
					'key' VALUE key,
					'value' VALUE value,
					'order' value split_num
					)
			)
	   from key_value_pairs
	  group by dynasty

<三>、不足

  • 有的键值对比较大,在ORACLE是CLOB类型,不支持字符串拆分,只能用如下MYSQL方法,再进行数据同步

三、MYSQL

<一>、键值对拆分(RECURSIVE)

  • MYSQL中没有正则字符串拆分函数,只能用递归进行拆分
sql 复制代码
with recursive kv_split as (
	select dynasty,
	       trim(substring_index(value,';',1)) as kv_pairs,
	       trim(substring(value,char_length(substring_index(value,';',1)) + 2)) as remaining,
	       1 as splt_num
	  from table
	  union all
	select dynasty,
	       trim(substring_index(remaining,';',1)) as kv_pairs,
	       trim(substring(remaining,char_length(substring_index(value,';',1)) + 2)) as remaining,
	       split_num + 1 as splt_num
	  from kv_split
	 where remaining != ''
)
	select dynasty,kv_pairs,splt_num from kv_split

执行完为如下形式,跟ORACLE大同小异

dynasty part_num kv_pairs
唐朝 1 唐太宗:李世民
唐朝 2 唐高宗:李治
唐朝 3 唐玄宗:李隆基
汉朝 1 汉高祖:刘邦
汉朝 2 汉文帝:刘恒
汉朝 3 汉景帝:刘启
汉朝 4 汉武帝:刘彻
...

<二>、转为JSON

转成JSON跟ORACLE一样,有现成的转JSON函数,完整代码如下所示

sql 复制代码
with recursive kv_split as (
	select dynasty,
	       trim(substring_index(value,';',1)) as kv_pairs,
	       trim(substring(value,char_length(substring_index(value,';',1)) + 2)) as remaining,
	       1 as splt_num
	  from table
	  union all
	select dynasty,
	       trim(substring_index(remaining,';',1)) as kv_pairs,
	       trim(substring(remaining,char_length(substring_index(value,';',1)) + 2)) as remaining,
	       split_num + 1 as splt_num
	  from kv_split
	 where remaining != ''
)
	select dynasty,
	       json_arrayagg(
				json_object(
					'key',cast(substring_index(kv_pairs,':',1) as unsigned),
					'value',substring_index(kv_pairs,':',-1),
					'order',split_num
					)
			) as json_result
	  from kv_split
	 group by dynasty
相关推荐
成为大佬先秃头44 分钟前
数据库连接池:Druid
数据库·mysql·druid
晓华-warm3 小时前
Warm-Flow 1.8.5 正式发布:超时自动审批、暂存功能来了!
数据库
u0136863824 小时前
将Python Web应用部署到服务器(Docker + Nginx)
jvm·数据库·python
light blue bird5 小时前
多页签Razor组支轴业务整顿组件
数据库·.net·ai大数据·多功能图表报表·web mvc + razor
wregjru5 小时前
【mysql】2.数据表操作
数据库·mysql
手握风云-5 小时前
基于 Java 的网页聊天室(三)
服务器·前端·数据库
LcVong5 小时前
MySQL 5.2/5.7 开启Binlog日志详细步骤(附验证+查看+恢复)
数据库·mysql·adb
FL4m3Y4n5 小时前
MySQL缓存策略
数据库·mysql·缓存
wsx_iot5 小时前
TDengine学习
数据库·学习·tdengine
不吃香菜的小趴菜6 小时前
mysql数据库打包与导入
数据库·mysql