使用 MySQL 从 JSON 字符串提取数据

使用 MySQL 从 JSON 字符串提取数据

在现代数据库管理中,JSON 格式因其灵活性而广泛使用。然而,当数据存储在 JSON 中时,我们经常需要将其转换为更易于处理的格式。本篇文章将通过一个具体的 SQL 查询示例,展示如何从存储在 MySQL 中的 JSON 字符串提取数据并重新格式化。

1. 背景知识

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。MySQL 从版本 5.7 开始支持 JSON 数据类型,使得在数据库中存储和操作 JSON 数据成为可能。

在许多应用中,JSON 字符串可能存储在表的某个字段中,我们需要提取和转换这些数据以便进行进一步分析或展示。

2. 示例数据

假设我们在 wf_lcdy 表中有一个字段 lct,其中存储了如下 JSON 字符串:

复制代码
{"15775d64e52c4ba3a8eef4bafc5f40e5":"875 162","75b67fab657748a9ab4bba141bfa0d36":"375 98","428299fd90814b3eaf129e8246f82b2a":"155 126"}

我们希望将其转换为以下格式的数组:

复制代码
[{"id":"15775d64e52c4ba3a8eef4bafc5f40e5","x":875,"y":162},{"id":"75b67fab657748a9ab4bba141bfa0d36","x":375,"y":98},{"id":"428299fd90814b3eaf129e8246f82b2a","x":155,"y":126}]
3. SQL 查询分析

以下是实现这一转换的 SQL 查询:

复制代码
SELECT
    CONCAT('[', GROUP_CONCAT(
            CONCAT(
                    '{"id":"',
                    SUBSTRING_INDEX(SUBSTRING_INDEX(kv, ':', 1), '"', -1),
                    '", "x":',
                    CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(kv, ':', -1), ' ', 1) AS UNSIGNED),
                    ', "y":',
                    CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(kv, ':', -1), ' ', -1) AS UNSIGNED),
                    '}'
            )
                ), ']') AS result
FROM (
         SELECT
             TRIM(BOTH '"' FROM kv) AS kv
         FROM (
                  SELECT
                      SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE(REPLACE(REPLACE(lct, '{', ''), '}', ''), '"', ''), ',', numbers.n), ',', -1) AS kv
                  FROM wf_lcdy
                           JOIN (
                      SELECT 1 AS n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL
                      SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL
                      SELECT 9 UNION ALL SELECT 10
                  ) numbers
                  WHERE CHAR_LENGTH(lct) - CHAR_LENGTH(REPLACE(lct, ',', '')) >= numbers.n - 1 AND ID = '0c86346993d64d98ad17892974bf8963'
              ) AS temp
     ) AS kv_pairs;
3.1 查询结构解析
  1. 内层查询

    • 去除多余字符 :首先,使用 REPLACE 函数将 lct 字段中的 {}" 去掉。这样可以简化后续处理。

    • 分割字符串 :使用 SUBSTRING_INDEX 将每个键值对分割开。我们通过一个数字表(1到10)来实现。数字表的作用是帮助我们迭代处理每个键值对,因为我们无法预先知道 JSON 中键值对的数量。

      SELECT

      SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE(REPLACE(REPLACE(lct, '{', ''), '}', ''), '"', ''), ',', numbers.n), ',', -1) AS kv

    这段代码将 JSON 字符串拆分为多个键值对,kv 列中将包含这样的值,例如:

    • 15775d64e52c4ba3a8eef4bafc5f40e5:875 162
    • 75b67fab657748a9ab4bba141bfa0d36:375 98
    • 428299fd90814b3eaf129e8246f82b2a:155 126
  2. 中层查询

    • 在此查询中,我们会对 kv 列进行进一步处理。使用 TRIM(BOTH '"' FROM kv) 去掉多余的引号,以确保后续操作不会受到影响。

      SELECT

      TRIM(BOTH '"' FROM kv) AS kv

  3. 外层查询

    • 聚合和格式化 :在外层查询中,我们使用 GROUP_CONCAT 聚合所有的 kv 对,并使用 CONCAT 生成目标格式的 JSON 字符串。

    • 提取数据 :使用 SUBSTRING_INDEX 提取 idxy 的值,并将它们转换为相应的格式。这里的关键在于分割字符串并提取数字。

      GROUP_CONCAT(

      CONCAT(

      '{"id":"',

      SUBSTRING_INDEX(SUBSTRING_INDEX(kv, ':', 1), '"', -1),

      '", "x":',

      CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(kv, ':', -1), ' ', 1) AS UNSIGNED),

      ', "y":',

      CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(kv, ':', -1), ' ', -1) AS UNSIGNED),

      '}'

      )

      )

    • 最终结果:最终的结果将是一个字符串,格式为 JSON 数组。

4. 查询结果

运行上述查询后,您将得到所需的结果格式:

复制代码
[{"id":"15775d64e52c4ba3a8eef4bafc5f40e5","x":875,"y":162},{"id":"75b67fab657748a9ab4bba141bfa0d36","x":375,"y":98},{"id":"428299fd90814b3eaf129e8246f82b2a","x":155,"y":126}]
5. 性能考虑
  • 字符长度计算CHAR_LENGTH(lct) - CHAR_LENGTH(REPLACE(lct, ',', '')) 的计算用于确保我们只处理存在的键值对。此方法对性能有一定影响,特别是对于大文本。
  • 数字表的使用:由于 JSON 的结构可能变化,数字表的使用可以扩展以支持更多的键值对。在实际应用中,您可以根据需要增加数字的范围。
6. 总结

通过上述 SQL 查询,我们成功地从一个包含 JSON 字符串的字段中提取了数据并转换成了另一种结构化格式。这种方法展示了 MySQL 在处理 JSON 数据方面的灵活性和强大能力。

在实际应用中,您可以根据具体的需求对查询进行适当的修改,以适应不同结构的 JSON 数据。此外,了解 SQL 中字符串处理和聚合函数的使用,对于提升数据处理的能力和效率至关重要。希望本篇文章对您在处理 JSON 数据时有所帮助!

相关推荐
Jess079 分钟前
MySQL内置函数
数据库·mysql
凉年技术27 分钟前
MySQL 5.6 2000 万行高频读写表新增字段实战:从慢执行到无锁落地全解析
mysql
Root_Hacker1 小时前
sql注入学习笔记
数据库·sql·web安全·网络安全·oracle·网络攻击模型
IT邦德1 小时前
基于OEL8环境的图形化部署Oracle26ai
数据库·oracle
一心赚狗粮的宇叔2 小时前
mongosDb 安装及Mongosshell常见命令
数据库·mongodb·oracle·nosql·web·全栈
hamawari2 小时前
SQL语法
数据库·sql·oracle
xiaoye37083 小时前
redis和mysql数据库如何保证数据一致性
redis·mysql
一条闲鱼_mytube3 小时前
MySQL vs PostgreSQL 对比
数据库·mysql·postgresql
小北方城市网3 小时前
Spring Boot 多数据源与事务管理实战:主从分离、动态切换与事务一致性
java·开发语言·jvm·数据库·mysql·oracle·mybatis