当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL JSON_TABLE NESTED PATH 没匹配时怎样保留父行

MySQL JSON_TABLE NESTED PATH 没匹配时怎样保留父行

来源:17golang原创 2026-11-14 03:09:35 0浏览 收藏

在 MySQL 8.4 中,JSON_TABLE() 的 NESTED PATH 没有匹配项时,默认不会把顶层父对象整行丢掉,而是保留父列,并为嵌套列生成一条值为 NULL 的补行。这个行为可以理解为顶层行与嵌套行之间的外连接;只有明确写过滤条件,才会把它收窄成“必须有子项”的结果。

记住两点:NESTED PATH 的无匹配结果是“父行保留、子列补 NULL”;FOR ORDINALITY 负责追踪行来自哪个父对象或哪个子对象。不要用是否出现子行来猜测父对象是否存在。

官方资料:https://dev.mysql.com/doc/refman/8.4/en/json-table-functions.html

先看清 JSON_TABLE 的行是怎样生成的

JSON_TABLE() 先根据最外层路径生成行源,再按 COLUMNS 中的列定义取值。顶层路径例如 '$[*]' 会让数组中的每个对象成为一条父行;NESTED PATH '$.items[*]' 则在每个父对象下面继续展开子数组。

因此,下面这份数据里,订单 1001 有两个商品,订单 1002 没有 items,订单 1003 的商品数组为空:

SELECT *
FROM JSON_TABLE(
  '[
    {"order_id": 1001, "items": [{"sku": "A"}, {"sku": "B"}]},
    {"order_id": 1002},
    {"order_id": 1003, "items": []}
  ]',
  '$[*]' COLUMNS (
    order_id INT PATH '$.order_id',
    NESTED PATH '$.items[*]' COLUMNS (
      sku VARCHAR(20) PATH '$.sku'
    )
  )
) AS jt;

顶层路径负责产生三个父对象。嵌套路径对 1001 找到两项,对 1002 和 1003 都找不到匹配项。关键是:找不到嵌套项并不等于顶层对象不存在。

JSON_TABLE 顶层父对象经过 NESTED PATH 后保留父行并生成 NULL 子列的结构示意图
图1:JSON_TABLE 的父行与 NESTED PATH 子行关系示意;子路径无匹配时保留父列并补出 NULL 子列。

NESTED PATH 没匹配为什么仍然有父行

MySQL 文档把这个行为定义为外连接效果:NESTED PATH 没有匹配时,嵌套列全部设为 NULL,同时产生一条补行。把上面的查询想象成结果集,得到的结构大致是:

order_idsku含义
1001A第一个子项
1001B第二个子项
1002NULL没有 items,父行仍保留
1003NULLitems 为空,父行仍保留

这条规则适合“即使没有明细,也要列出主表对象”的报表。例如订单对账、目录树检查和数据完整性盘点,都可能需要把没有子项的父对象显式展示出来。如果后续把 NULL 当成“没有父对象”,就会误判数据。

用默认值区分缺失列和 NULL 补行

NESTED PATH 产生补行后,嵌套列也会参与列级的 ON EMPTY 规则。默认的 NULL ON EMPTY 会得到 NULL;如果业务报表需要可读的占位值,可以在嵌套列上指定 DEFAULT。

SELECT *
FROM JSON_TABLE(
  '[
    {"order_id": 1001, "items": [{"sku": "A"}]},
    {"order_id": 1002}
  ]',
  '$[*]' COLUMNS (
    order_id INT PATH '$.order_id',
    NESTED PATH '$.items[*]' COLUMNS (
      -- 子路径没有匹配时,用文本占位而不是丢掉父行
      sku VARCHAR(20) PATH '$.sku' DEFAULT 'NO_ITEM' ON EMPTY
    )
  )
) AS jt;

这里的 DEFAULT 只改变嵌套列的取值,不会改变行生成规则。1002 仍然有一条父行,只是 sku 由 NULL 变成了 NO_ITEM。不要把它和 ON ERROR 混为一谈:前者处理路径缺失,后者处理对象转标量等转换错误。

用 FOR ORDINALITY 追踪父子记录关系

当父对象的业务字段可能重复时,单看 order_id 不足以判断两组子项属于哪个父对象。FOR ORDINALITY 会从 1 开始为当前 COLUMNS 层产生的行编号,因此可以在结果集中保存父层序号和子层序号。

SELECT *
FROM JSON_TABLE(
  '[
    {"customer": "same", "items": [{"sku": "A"}]},
    {"customer": "same", "items": [{"sku": "B"}, {"sku": "C"}]},
    {"customer": "empty"}
  ]',
  '$[*]' COLUMNS (
    -- 父层序号用来区分两个 customer 值相同的对象
    top_ord FOR ORDINALITY,
    customer VARCHAR(20) PATH '$.customer',
    NESTED PATH '$.items[*]' COLUMNS (
      -- 子层序号只在同一个父对象的子项中递增
      item_ord FOR ORDINALITY,
      sku VARCHAR(20) PATH '$.sku'
    )
  )
) AS jt
ORDER BY top_ord, item_ord;

这样得到的 top_ord 能回答“来自第几个顶层对象”,item_ord 能回答“在该对象中是第几个子项”。如果某个父对象没有 items,它仍会出现,但嵌套层的序号和 sku 都会是 NULL。

JSON_TABLE 使用 FOR ORDINALITY 标识父子记录并通过 WHERE 过滤 NULL 补行的流程示意图
图2:FOR ORDINALITY 与 WHERE 条件的结果关系示意;序号用于追踪来源,过滤条件决定是否留下补行。

什么时候要用 WHERE 把补行过滤掉

如果查询目标是“只要确实存在子项的父对象”,可以在外层对嵌套列添加条件。这个条件不是在改变 NESTED PATH 的行生成规则,而是在结果生成之后排除补行。

SELECT order_id, sku
FROM JSON_TABLE(
  '[
    {"order_id": 1001, "items": [{"sku": "A"}]},
    {"order_id": 1002}
  ]',
  '$[*]' COLUMNS (
    order_id INT PATH '$.order_id',
    NESTED PATH '$.items[*]' COLUMNS (
      sku VARCHAR(20) PATH '$.sku'
    )
  )
) AS jt
-- 只保留有实际子项的父对象,NULL 补行会被排除
WHERE sku IS NOT NULL;

过滤前适合做“主对象全量盘点”,过滤后适合做“明细存在性查询”。如果 sku 本身允许合法的 JSON null,就不要把它当作唯一判据,可以额外增加 EXISTS PATH 标记或选择一个不会为空的业务字段。

多个 NESTED PATH 不会自动做笛卡尔积

同一层写多个兄弟 NESTED PATH 时,MySQL 会依次处理它们;一个嵌套路径产出记录时,另一个嵌套路径的列会补成 NULL。因此总行数更接近各路径产出行数的相加,而不是两个子数组长度的相乘。

SELECT *
FROM JSON_TABLE(
  '{"a": [1, 2], "b": [10, 20]}',
  '$' COLUMNS (
    NESTED PATH '$.a[*]' COLUMNS (
      -- 第一组子数组产生两行,b 列在这些行中为空
      a_value INT PATH '$'
    ),
    NESTED PATH '$.b[*]' COLUMNS (
      -- 第二组子数组随后产生两行,a 列在这些行中为空
      b_value INT PATH '$'
    )
  )
) AS jt;

如果业务真的需要把两个数组按位置配对,应该先确认配对规则,再分别展开并用序号或其他键连接;不能看到两个 NESTED PATH 就假设会得到四行两两组合。

排查 JSON_TABLE 结果时的判断清单

现象优先判断处理方式
父列有值,子列为 NULL子路径没有匹配,产生补行确认是否需要保留父行,或用 WHERE 过滤
同名父字段无法区分来源业务值重复,缺少行身份增加父层 FOR ORDINALITY
缺失字段想显示占位文字路径缺失属于 ON EMPTY在嵌套列上配置 DEFAULT ... ON EMPTY
两个子数组结果行数比预期少或多兄弟 NESTED PATH 按顺序产出用序号明确配对规则,不假设笛卡尔积

常见问题

NESTED PATH 没有匹配时能不能让父行完全消失?

可以在外层对可靠的嵌套列使用 WHERE ... IS NOT NULL,或者使用 EXISTS PATH 生成存在性标记后过滤。默认行为仍然是保留父行。

NULL 补行是 ON ERROR 造成的吗?

不是。它来自 NESTED PATH 没有匹配时的补行语义;ON ERROR 处理的是对象、数组转标量或类型转换等错误。

FOR ORDINALITY 的序号能当业务主键吗?

不能把它当跨查询稳定的业务主键。它只表示当前 JSON_TABLE 结果中行的顺序,适合本次查询内追踪父子来源和构造临时关联。

为什么没有 items 的对象仍然返回一行?

因为顶层路径已经匹配到了该对象,NESTED PATH 只负责展开子路径;子路径无匹配时按外连接语义生成 NULL 补行。需要明细时再显式过滤。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
MySQL recursive CTE 怎样用 cte_max_recursion_depth 控制深度MySQL recursive CTE 怎样用 cte_max_recursion_depth 控制深度
上一篇
MySQL recursive CTE 怎样用 cte_max_recursion_depth 控制深度
MySQL utf8mb4 排序规则变化后为什么结果顺序不同
下一篇
MySQL utf8mb4 排序规则变化后为什么结果顺序不同
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之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模型性能。
    1018次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    1020次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1153次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1121次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    962次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码