You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL/MariaDB嵌套JSON多条件查询及模板递归关联需求

针对你的场景,我给你分两种情况提供适配MySQL 8.0.21和MariaDB 10.4.11的健壮解决方案:


1. 基础查询:获取直接引用指定模板的记录

你之前遇到的问题是JSON_SEARCH/JSON_EXTRACT无法处理数组中多个匹配元素的情况,这里用JSON_TABLE就能完美解决——它可以把JSON数组拆成关系型的行数据,让你像操作普通表一样筛选条件。

查询直接引用模板ID=1的SQL如下:

SELECT DISTINCT t.Id, t.TemplateData
FROM template t
JOIN JSON_TABLE(
    t.TemplateData,
    '$[*]' COLUMNS(
        type VARCHAR(20) PATH '$.type',
        template_id INT PATH '$.id'
    )
) jt
WHERE jt.type = 'template' AND jt.template_id = 1;

这个语句会把每条记录的TemplateData数组拆成独立的行,然后筛选出type为template且id等于1的条目,最后用DISTINCT避免同一条记录被多次匹配。执行后会精准返回Id=2和4的记录,完全符合你的预期。

和LIKE表达式不同,这个方法完全基于JSON结构解析,不受属性顺序、空格或引号格式变化的影响,稳定性拉满。


2. 进阶查询:递归获取所有直接+间接引用的记录

如果要包含间接引用(比如Id=5引用Id=2,而Id=2引用Id=1,所以查询Id=1时要返回Id=2、4、5),可以用**递归CTE(公共表表达式)**来实现,这两个数据库版本都支持这个特性。

对应的SQL语句:

WITH RECURSIVE referenced_templates AS (
    -- 第一步:先找出直接引用目标模板的记录
    SELECT t.Id, t.TemplateData
    FROM template t
    JOIN JSON_TABLE(
        t.TemplateData,
        '$[*]' COLUMNS(
            type VARCHAR(20) PATH '$.type',
            template_id INT PATH '$.id'
        )
    ) jt
    WHERE jt.type = 'template' AND jt.template_id = 1

    UNION ALL

    -- 第二步:递归查找引用了已找到模板的记录
    SELECT t.Id, t.TemplateData
    FROM template t
    JOIN JSON_TABLE(
        t.TemplateData,
        '$[*]' COLUMNS(
            type VARCHAR(20) PATH '$.type',
            template_id INT PATH '$.id'
        )
    ) jt
    JOIN referenced_templates rt ON jt.template_id = rt.Id
    WHERE t.Id NOT IN (SELECT Id FROM referenced_templates) -- 防止循环引用导致无限递归
)
SELECT DISTINCT Id, TemplateData FROM referenced_templates;

这个逻辑的核心是:

  • 初始查询先拿到直接引用目标模板的记录(Id=2、4);
  • 递归步骤会不断查找那些引用了当前结果集中模板的记录,比如Id=5引用了Id=2,所以会被加入结果;
  • 最后的WHERE t.Id NOT IN (...)是为了避免循环引用(如果你的模板存在互相引用的情况),防止无限递归。

执行这个语句后,会返回Id=2、4、5的记录,满足你需要的间接关联查询需求。


内容的提问来源于stack exchange,提问作者MIB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 18:12:40