使用 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 数据时有所帮助!

相关推荐
番茄去哪了7 小时前
从0到1独立开发一个论坛项目(一)
java·数据库·oracle·maven
1688red7 小时前
基于Canal实现MySQL到Elasticsearch的数据同步
数据库·mysql·elasticsearch
我真会写代码8 小时前
从底层到实战:MySQL核心原理拆解,解锁数据库高性能密码
数据库·mysql
LF3_8 小时前
监听数据库binlog日志变化,将变动实时发送到kafka
数据库·分布式·mysql·kafka·binlog·debezium
江不清丶8 小时前
事务隔离级别深度解析:从理论到MySQL实现
数据库·mysql
小狗丹尼4009 小时前
JSON 基础认知、数据转换与 Flask 前后端交互全解
python·flask·json
百结21416 小时前
Mysql数据库操作
数据库·mysql·oracle
ego.iblacat17 小时前
MySQL 服务基础
数据库·mysql
Maverick0618 小时前
Oracle Redo 日志操作手册
数据库·oracle
攒了一袋星辰19 小时前
高并发强一致性顺序号生成系统 -- SequenceGenerator
java·数据库·mysql