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

递归CTE中WHERE条件疑问:为何生成2011-01-01日期?

递归CTE中WHERE条件的作用机制及超出预期日期的原因

问题核心

你遇到的现象本质是:递归CTE的UNION ALL分支中,WHERE条件过滤的是「当前迭代的源行」,而非即将生成的新行。

具体逻辑拆解

你的原始查询执行流程如下:

  1. 初始行:id=1, ymd='2010-01-01',直接加入结果集。
  2. 第一次递归:检查源行ymd='2010-01-01'是否满足ymd < '2011-01-01',条件成立,生成新行ymd='2010-02-01'并加入结果集。
  3. 重复迭代,直到源行是ymd='2010-12-01'时:
    • '2010-12-01' < '2011-01-01'条件仍然成立,因此会基于该行生成新行ymd='2011-01-01'并加入结果集。
  4. 下一次迭代尝试用ymd='2011-01-01'作为源行,此时'2011-01-01' < '2011-01-01'不成立,递归终止。

这就是为什么结果最后一行是2011-01-01——它是在源行2010-12-01满足条件时生成的,之后才终止递归。

修正方案

要让结果截止到2010-12-01,需要调整WHERE条件,确保只有当生成的新行符合预期范围时,才执行递归生成。有两种常用写法:

写法一:基于即将生成的日期判断

WITH RECURSIVE datesCte AS
(
  SELECT 1 id, date('2010-01-01') as ymd, 2010 year, 1 month, 1 quarter 
  UNION ALL
  SELECT id+1, @d:=date_add(ymd,interval 1 month), year(@d), month(@d), quarter(@d)  
  FROM datesCte 
  WHERE date_add(ymd, interval 1 month) <= '2010-12-01'
)
SELECT * FROM datesCte 

写法二:基于当前源行的日期限制

WITH RECURSIVE datesCte AS
(
  SELECT 1 id, date('2010-01-01') as ymd, 2010 year, 1 month, 1 quarter 
  UNION ALL
  SELECT id+1, @d:=date_add(ymd,interval 1 month), year(@d), month(@d), quarter(@d)  
  FROM datesCte 
  WHERE ymd < '2010-12-01'
)
SELECT * FROM datesCte 

两种写法都能确保最后生成的行是2010-12-01,且递归在生成该行后终止。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 06:04:57