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
相关推荐
合方圆~小文10 分钟前
AI摄像头精准识别技术依赖于深度算法
数据结构·数据库·数码相机·模块测试
tanxiaomi21 分钟前
Redis相关面试题
数据库·redis·缓存
钮钴禄·爱因斯晨44 分钟前
【探索实战】KuratorGitOps 多环境配置管理与合规审计
数据库
Z***G4791 小时前
【零基础学Mysql】常用函数讲解,提升数据操作效率的利器
数据库·mysql
q***06471 小时前
Spring Boot 从 2.7.x 升级到 3.3注意事项
数据库·hive·spring boot
aml258__1 小时前
MySQL 数据库管理入门:从创建到删除(T1)
数据库·mysql·oracle·初学数据库
悦悦欧呐呐呐呐1 小时前
数据库事务是什么,怎么用的
服务器·数据库·oracle
q***64971 小时前
Spring Boot 各种事务操作实战(自动回滚、手动回滚、部分回滚)
java·数据库·spring boot
忘记9261 小时前
mybatis是什么
数据库·oracle·mybatis
q***92512 小时前
Springboot3 Mybatis-plus 3.5.9
数据库·oracle·mybatis