使用 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 提取 id、x 和 y 的值,并将它们转换为相应的格式。这里的关键在于分割字符串并提取数字。

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

相关推荐
imDwAaY26 分钟前
一条 SQL 发出去之后,MySQL 到底做了什么?
sql·mysql
行业研究员1 小时前
Agent Memory降低Token消耗原理解析
数据库·人工智能·oracle·腾讯云·智能体
March.s2 小时前
MySQL 数据库原理与实战:从数据管理到 LAMP 建站全解
数据库·mysql
悟道子HD2 小时前
网络安全基本功——MySQL基础
android·mysql·web安全
晚风叙码2 小时前
MySQL 增删改查(CRUD)完全指南:从入门到面试
数据库·mysql·面试
程序员Sunday15 小时前
MySQL 为什么使用 B+ 树索引?把范围查询、回表和覆盖索引连起来
数据库·mysql
Yyyyyy~15 小时前
[ Mysql ] 库的操作
mysql
小米里的大麦15 小时前
16 MySQL 事务
数据库·mysql
Titan202416 小时前
MySQL访问个人学习笔记
笔记·学习·mysql
for_ever_love__17 小时前
MySQL 全文索引实战:FULLTEXT、ngram 中文分词与 MATCH AGAINST 到底该怎么用
java·python·mysql·全文检索·分词·索引·ngram