当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > MySQL JSON_TABLE 如何拆分嵌套数组:路径映射、行扩展与空值边界

MySQL JSON_TABLE 如何拆分嵌套数组:路径映射、行扩展与空值边界

来源:17golang原创 2026-08-29 10:38:45 0浏览 收藏

订单服务把商品明细暂存在 JSON 列里时,真正麻烦的通常不是取出一个字段,而是把“一个订单—多个商品—多个批次”拆成能过滤、统计和追查的行。MySQL 的 JSON_TABLE() 可以完成这次展开,但路径写错时,结果会悄悄少行,空数组也可能让人误以为数据丢了。

先用顶层 '$[*]' 生成订单行,再用相对父路径的 NESTED PATH 展开商品和批次;没有匹配项时,MySQL 会补出一行 NULL,是否保留它要由查询条件决定。

要点速览

  • JSON_TABLE() 的每个 PATH 都相对当前行路径解析。
  • NESTED PATH '$.items[*]' 会把一个订单行扩展为多个商品行。
  • 商品对象缺少 batches 时,嵌套列默认以 NULL 补行。
  • 标量类型转换与缺失字段要分别用 ON ERROR、ON EMPTY 处理。

先固定一份可观察的订单 JSON

下面的示例故意保留两个边界:订单 1002 没有 batches,订单 1003 的商品数组为空。这样能直接看出“没有匹配”和“有匹配但值为空”不是一回事。

SET @orders = '[
  {"order_id":1001,"items":[
    {"sku":"A-10","qty":2,"batches":[{"no":"B01","qty":1},{"no":"B02","qty":1}]},
    {"sku":"B-20","qty":1,"batches":[{"no":"B09","qty":1}]}
  ]},
  {"order_id":1002,"items":[{"sku":"C-30","qty":4}]},
  {"order_id":1003,"items":[]}
]';

这里的 items 是订单对象的数组,batches 又是商品对象的数组。查询要做的是把父级的 order_id 带到每个商品行,再把 sku 带到每个批次行。

用 NESTED PATH 完成两层行扩展

顶层路径 '$[*]' 先选中每个订单对象;第一个 NESTED PATH '$.items[*]' 相对订单对象展开商品;第二个嵌套路径则相对商品对象展开 batches。短标签只用于说明链路,字段名仍以 SQL 为准。

SELECT jt.order_id, jt.sku, jt.item_qty, jt.batch_no, jt.batch_qty
FROM JSON_TABLE(
  @orders,
  '$[*]' COLUMNS (
    order_id INT PATH '$.order_id',
    NESTED PATH '$.items[*]' COLUMNS (
      sku VARCHAR(20) PATH '$.sku',
      item_qty INT PATH '$.qty',
      NESTED PATH '$.batches[*]' COLUMNS (
        batch_no VARCHAR(20) PATH '$.no',
        batch_qty INT PATH '$.qty'
      )
    )
  )
) AS jt
ORDER BY jt.order_id, jt.sku, jt.batch_no;
MySQL JSON_TABLE 从 orders 经过 items 到 batches 的两层行扩展,标出 order_id、sku、batch_no 数据路径

图中的 orders、items、batches 和 row expansion 是同一条数据路径的四个观察点:从父对象进入数组,再落成关系行。

对订单 1001,A-10 产生两行、B-20 产生一行;父列 order_id 会复制到展开后的子行。订单 1002 没有批次时,仍可能出现一行商品记录,只是 batch_no 和 batch_qty 为 NULL。

为什么空数组会补 NULL 行

NESTED PATH 没有匹配项时,MySQL 会为嵌套列生成 NULL-complemented row。这是为了保留父级行,行为更接近外连接;如果业务只要“确实有批次”的结果,再显式过滤 batch_no IS NOT NULL。

-- 保留订单与商品,即使商品没有批次
SELECT order_id, sku, batch_no
FROM (...上面的 JSON_TABLE...) AS jt;

-- 只统计实际批次
SELECT order_id, sku, batch_no, batch_qty
FROM (...上面的 JSON_TABLE...) AS jt
WHERE batch_no IS NOT NULL;

别把 WHERE batch_no IS NOT NULL 提前写进 JSON 路径。路径负责描述数据层级,过滤负责表达业务口径;分开写更容易检查“缺批次的商品是否应该保留”。

MySQL JSON_TABLE 缺少 batches 时保留父级商品行并将 batch_no 置为 NULL,随后由过滤条件决定是否保留

第二张图把这个边界压缩成四个观察点:parent row 进入 NESTED PATH,缺少子数组时得到 NULL,最后交给 filter 决定是否保留。

ON EMPTY 与 ON ERROR 要分开判断

字段不存在是 empty,找到字段但值无法转换成目标类型则是 error。比如 qty 缺失时可以给默认值;qty 是数组却映射到 INT 时,应该让错误暴露,避免把坏数据当成正常数量。

SELECT jt.sku, jt.item_qty
FROM JSON_TABLE(
  @orders,
  '$[*]' COLUMNS (
    NESTED PATH '$.items[*]' COLUMNS (
      sku VARCHAR(20) PATH '$.sku' ERROR ON EMPTY,
      item_qty INT PATH '$.qty'
        DEFAULT '0' ON EMPTY
        ERROR ON ERROR
    )
  )
) AS jt;

生产查询中建议显式写出这两个选项,并在测试数据里覆盖缺字段、空值、字符串数字和数组误填四种情况。MySQL 8.0.20 起,ON ERROR 放在 ON EMPTY 前面已不推荐,书写顺序保持“先 empty、后 error”。

两个容易误判的结果

父列为什么重复

这是行展开的必然结果:父级订单不是被复制成多份 JSON,而是作为关系结果中的关联列出现在每个子行。统计订单数时用 COUNT(DISTINCT order_id),统计批次数量时再按 batch_no 口径聚合。

兄弟 NESTED PATH 为什么不是笛卡尔积

同一层的两个兄弟嵌套路径会依次产出记录,另一条路径的列在当前记录中置为 NULL,总行数是各路径行数之和,而不是两者相乘。需要成对组合时,应先分别展开成派生表,再按明确键连接。

一份可复用的检查清单

  • 先确认每个 PATH 是相对顶层对象还是相对父级 NESTED PATH。
  • 用一个空数组和一个缺字段对象验证 NULL 补行是否符合业务口径。
  • 对数量、金额等字段同时测试 ON EMPTY 与 ON ERROR。
  • 统计父级实体时避免直接对展开后的父列做 COUNT(*)。

相关问题

JSON_TABLE 能直接修改原 JSON 吗?

不能。它返回的是关系结果集;要修改 JSON 列,应使用 JSON 修改函数或在应用层完成写回。

空的 items 数组一定会产生商品行吗?

不会凭空产生商品值。父级是否保留、嵌套列是否补 NULL,要结合所在层级和查询过滤条件观察。

什么时候应该把 JSON 拆成真实子表?

当商品、批次需要高频筛选、关联、约束或增量更新时,真实子表通常更易维护;JSON_TABLE 更适合边界明确的导入、清洗和一次性展开。

把路径和业务口径一起验收

JSON_TABLE 的关键不是记住一段语法,而是把每一级数组对应到一组结果行,再明确空数组、缺字段和坏类型各自的处理方式。先用小样本核对 order_id → sku → batch_no 的行数,再把过滤和聚合加回正式查询,问题通常会在上线前暴露。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
MCP 远程服务器如何限制工具权限:allowlist、来源校验与审计留痕MCP 远程服务器如何限制工具权限:allowlist、来源校验与审计留痕
上一篇
MCP 远程服务器如何限制工具权限:allowlist、来源校验与审计留痕
多模态模型处理 PDF 表格如何避免跨页字段错位:分页切片、表头继承与行号复核
下一篇
多模态模型处理 PDF 表格如何避免跨页字段错位:分页切片、表头继承与行号复核
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    463次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    526次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    543次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    490次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    309次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码