MySQL递归CTE拆分/::/分隔字符串仅获最后项,如何获取所有结果?
解决递归CTE拆分字符串仅返回最后一项的问题
你的递归CTE出现问题的核心原因是分隔符数量计算错误:你直接用LENGTH(FIELDVALUE) - LENGTH(REPLACE(FIELDVALUE, '/::/', ''))得到的是所有分隔符的总字符长度(/::/占4个字符,两个分隔符就是8),而非分隔符的实际个数。这会导致递归条件判断错误,递归次数远超过实际需要的次数,当StartIndex+1超过实际项数时,SUBSTRING_INDEX会返回整个字符串,取-1就一直得到最后一项。
修改后的递归CTE语句
WITH RECURSIVE ProductCTE AS ( SELECT b.fieldvalue AS FIELDVALUE, SUBSTRING_INDEX(b.fieldvalue, '/::/', 1) AS ProductName, 1 AS StartIndex, -- 计算当前字符串的分隔符实际个数 (LENGTH(b.fieldvalue) - LENGTH(REPLACE(b.fieldvalue, '/::/', ''))) / LENGTH('/::/') AS SeparatorCount FROM baselineversionfield b where b.documentfieldid = 458 UNION ALL SELECT FIELDVALUE, SUBSTRING_INDEX(SUBSTRING_INDEX(FIELDVALUE, '/::/', StartIndex + 1), '/::/', -1) AS ProductName, StartIndex + 1 AS StartIndex, SeparatorCount FROM ProductCTE WHERE -- 递归终止条件:当前索引小于等于分隔符个数(因为项数=分隔符个数+1) StartIndex <= SeparatorCount ) SELECT StartIndex AS 序号, ProductName AS 拆分项 FROM ProductCTE ORDER BY FIELDVALUE, StartIndex;
修改说明
- 新增
SeparatorCount字段:在初始查询中计算出每个字符串的实际分隔符个数,避免每次递归重复计算,同时确保判断准确。 - 修正递归终止条件:将错误的项数判断改为
StartIndex <= SeparatorCount,因为项数=分隔符个数+1,初始StartIndex=1对应第一项,递归到StartIndex=SeparatorCount时刚好生成最后一项,之后停止递归。 - 新增排序与字段别名:添加
ORDER BY保证拆分项的顺序正确,同时给字段起直观的别名,方便查看结果。
效果验证
对于示例字符串Sample Set/::/itemtypes/::/Baselines,SeparatorCount的值为2,递归过程如下:
- 初始行:
StartIndex=1,返回Sample Set - 第一次递归:
StartIndex=1 <=2,返回itemtypes,StartIndex变为2 - 第二次递归:
StartIndex=2 <=2,返回Baselines,StartIndex变为3 - 第三次递归判断:
3 <=2不成立,终止递归
最终返回3条正确的拆分记录,序号和拆分项一一对应。
内容的提问来源于stack exchange,提问作者gunnersboy
相关产品推荐
相关产品推荐

