MySQL递归CTE查询:基于GetTicketNumbers表生成序列行
问题描述
现有GetTicketNumbers表数据如下:
i UID TicketNumber 2 09901a22c7c3acc6786847c775f1d113 10 6 00dad28bef21f916240d6e8c1c1bd67d 5 12 00dad28bef21f916240d6e8c1c1bd67d 20
需要生成总计35行结果(必须保留UID用于上层关联):对应原表i=2的行生成10条序列行,i=6的行生成5条,i=12的行生成20条。现有不完整的递归CTE查询,请求补全:
With RECURSIVE cte (i, UID, TicketNumbers) as ( Select i, UID, TicketNumbers from GetTicketNumbers union all Select i + 1, UID, TicketNumbers from cte where ????? ) select * from cte order by i;
环境为MySQL。
解决方案
首先要明确递归终止逻辑:对每一行初始数据,需生成从原i开始的连续TicketNumber行数据。原CTE缺少对起始i的记录,无法正确判断递归终止时机,以下是两种可行的补全方案:
方案一:新增起始值字段(推荐,效率更高)
通过新增start_i字段存储初始行的i值,避免递归时重复查询原表,逻辑更清晰:
WITH RECURSIVE cte (i, UID, TicketNumber, start_i) AS ( -- 初始查询:保留原始行的i作为起始值start_i SELECT i, UID, TicketNumber, i FROM GetTicketNumbers UNION ALL -- 递归生成下一行,直到当前i达到起始i + TicketNumber - 1 SELECT i + 1, UID, TicketNumber, start_i FROM cte WHERE i < start_i + TicketNumber - 1 ) -- 输出所需列,去掉临时的start_i字段 SELECT i, UID, TicketNumber FROM cte ORDER BY i;
方案二:使用子查询获取起始值(不修改原CTE结构)
如果要保留原CTE的字段结构,可通过子查询获取当前行的起始i值,补全WHERE条件:
WITH RECURSIVE cte (i, UID, TicketNumber) AS ( SELECT i, UID, TicketNumber FROM GetTicketNumbers UNION ALL SELECT i + 1, UID, TicketNumber FROM cte WHERE i < (SELECT g.i FROM GetTicketNumbers g WHERE g.UID = cte.UID AND g.TicketNumber = cte.TicketNumber) + cte.TicketNumber - 1 ) SELECT * FROM cte ORDER BY i;
效果说明
两种方案都能生成符合要求的35行数据:
i=2生成10行(范围2~11)i=6生成5行(范围6~10)i=12生成20行(范围12~31)
且全程保留UID字段,满足上层关联需求。
内容的提问来源于stack exchange,提问作者Alex-1999
相关产品推荐
相关产品推荐

