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

如何在MySQL查询中动态添加INNER JOIN实现版本历史递归查询

MySQL 动态查询版本链解决方案

你当前写死INNER JOIN的方式只能适配固定长度的版本历史,针对任意长度的版本链需求,根据你使用的MySQL版本可以选择以下两种方案:

方案1:MySQL 8.0+ 递归CTE(推荐)

MySQL 8.0开始支持的递归公共表表达式可以直接遍历自关联的树形结构,不需要手动拼接JOIN语句,自动适配任意长度的版本链。

行式输出(更通用,无需调整代码)

如果可以接受每个版本占一行的输出格式,直接使用以下语句即可查询任意版本的完整历史,只需修改锚点查询的WHERE id = 12为你要查询的最新版本id即可:

WITH RECURSIVE version_chain AS (
    -- 锚点:先定位到要查询的最末端版本
    SELECT id, first, ik_next, 1 AS version_index
    FROM first_next
    WHERE id = 12
    UNION ALL
    -- 递归:每次关联上一个版本
    SELECT fn.id, fn.first, fn.ik_next, vc.version_index + 1
    FROM first_next fn
    INNER JOIN version_chain vc ON fn.id = vc.ik_next
)
-- 按版本先后排序输出
SELECT id, first AS version_name, version_index
FROM version_chain
ORDER BY version_index DESC;

列式输出(和你原有查询输出格式一致)

如果需要和你原写法一样,每个版本作为单独的列输出,可以结合动态SQL自动生成对应列:

SET @query_sql = NULL;
-- 先获取版本链的所有节点
WITH RECURSIVE version_chain AS (
    SELECT id, first, ik_next, 1 AS version_index
    FROM first_next
    WHERE id = 12
    UNION ALL
    SELECT fn.id, fn.first, fn.ik_next, vc.version_index + 1
    FROM first_next fn
    INNER JOIN version_chain vc ON fn.id = vc.ik_next
)
-- 动态拼接每一列的查询逻辑
SELECT GROUP_CONCAT(
    CONCAT(
        'MAX(IF(version_index = ', version_index, ', id, NULL)) AS id_v', version_index, ', ',
        'MAX(IF(version_index = ', version_index, ', version_name, NULL)) AS name_v', version_index
    ) ORDER BY version_index DESC
) INTO @query_sql
FROM (SELECT id, first AS version_name, version_index FROM version_chain) t;

-- 拼接完整查询语句
SET @query_sql = CONCAT('
WITH RECURSIVE version_chain AS (
    SELECT id, first, ik_next, 1 AS version_index
    FROM first_next
    WHERE id = 12
    UNION ALL
    SELECT fn.id, fn.first, fn.ik_next, vc.version_index + 1
    FROM first_next fn
    INNER JOIN version_chain vc ON fn.id = vc.ik_next
)
SELECT ', @query_sql, ' FROM (SELECT id, first AS version_name, version_index FROM version_chain) t;
');

-- 执行动态查询
PREPARE stmt FROM @query_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

方案2:MySQL 5.x 兼容方案

如果你使用的是不支持CTE的低版本MySQL,可以使用用户变量迭代的方式遍历版本链:

SELECT 
  @id := id AS id,
  first AS version_name,
  @level := @level + 1 AS version_index
FROM 
  first_next,
  (SELECT @id := 12, @level := 0) init
WHERE 
  FIND_IN_SET(id, @id)
  AND LENGTH(@id := CONCAT(@id, ',', ik_next)) > 0
ORDER BY version_index DESC;

内容的提问来源于stack exchange,提问作者eboulme62980.fr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:36:04