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
相关推荐
计算机毕设VX:Fegn089517 小时前
计算机毕业设计|基于springboot + vue医院设备管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
Mr__Miss17 小时前
保持redis和数据库一致性(双写一致性)
数据库·redis·spring
Knight_AL18 小时前
Spring 事务传播行为 + 事务失效原因 + 传播行为为什么不用其他模式
数据库·sql·spring
倔强的石头_18 小时前
时序数据时代的“存储与分析困局”解析及金仓解决方案
数据库
计算机毕设VX:Fegn089518 小时前
计算机毕业设计|基于springboot + vue小型房屋租赁系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
倔强的石头_19 小时前
场景化落地指南——金仓时序数据库在关键行业的应用实践
数据库
SelectDB20 小时前
驾驭 CPU 与编译器:Apache Doris 实现极致性能的底层逻辑
运维·数据库·apache
zbguolei20 小时前
MySQL根据身份证号码计算出生日期和年龄
数据库·mysql
马克学长21 小时前
SSM校园图书借阅服务系统jd2z8(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·图书管理系统·ssm 框架·ssm 校园图书借阅系统
软件派21 小时前
高斯数据库使用心得——从性能优化到行业实践的深度解析
数据库·oracle