CTE 不经过递归

Posted

技术标签:

【中文标题】CTE 不经过递归【英文标题】:CTE not going through recursion 【发布时间】:2011-07-26 17:28:36 【问题描述】:

我是第一次使用 CTE,遇到了一些困难。我在网上查看并尝试拼凑示例。

我想在返回的每两行之间插入行,以说明其间的所有天数。第 1 行有 Date(A),第 2 行有 Date(B)。我想在 A 和 B 之间的每一天插入一行,其中这些行的值都与第 1 行相同。

如果我只对我的测试数据运行我的锚定义,我会得到 341 行。运行 CTE 后,我得到 682。所以它只运行一次。

您能提供的任何建议都会很棒。谢谢。

我有以下表架构:

field1 (varchar(10)) field2 (smalldatetime) field3 (numeric(18,0)) field4 (numeric(18,6)) field5 (numeric(18,6)) field6 (numeric(18,3))

输入表的一个例子是:

ABC  1-1-1990   0  0.1   0.1   0.125
ABC  1-5-1990   1  0.2   0.2   1.0
ABC  1-9-1990   0  0.3   0.3   0.750
ABC  1-13-1990  1  0.4   0.4   1.500

我想把它变成这样:

ABC  1-1-1990    0  0.1   0.1   0.125
ABC  1-2-1990    0  0.1   0.1   0.125
ABC  1-3-1990    0  0.1   0.1   0.125
ABC  1-4-1990    0  0.1   0.1   0.125
ABC  1-5-1990    1  0.2   0.2   1.0
ABC  1-6-1990    1  0.2   0.2   1.0
ABC  1-7-1990    1  0.2   0.2   1.0
ABC  1-8-1990    1  0.2   0.2   1.0
ABC  1-9-1990    0  0.3   0.3   0.750
ABC  1-10-1990   0  0.3   0.3   0.750
ABC  1-11-1990   0  0.3   0.3   0.750
ABC  1-12-1990   0  0.3   0.3   0.750
ABC  1-13-1990   1  0.4   0.4   1.500

这是我目前的 CTE:

WITH NewData (field1,field2,field3,field4,field5,field6) AS        
(        
    SELECT  m.field1,m.field2,m.field3,m.field4,m.field5,m.field6
    FROM    MyTable as m
    WHERE m.field1 is not null        
    GROUP BY m.field1,m.field2,m.field3,m.field4,m.field5,m.field6      
    UNION ALL        
    SELECT  m.field1, DATEADD(d, 1, m.field2), m.field3, m.field4, m.field5, m.field6   
    FROM MyTable as m              
)
SELECT  field1,field2,field3, field4, field5,field6    
FROM NewData
order by field1, field2
OPTION(MAXRECURSION 0)

当前输出(错过日期 1-3-1990、1-4-1990、1-7-1990、1-8-1990、1-11-1990、1-12-1990):

ABC  1-1-1990    0  0.1   0.1   0.125
ABC  1-2-1990    0  0.1   0.1   0.125
ABC  1-5-1990    1  0.2   0.2   1.0
ABC  1-6-1990    1  0.2   0.2   1.0
ABC  1-9-1990    0  0.3   0.3   0.750
ABC  1-10-1990   0  0.3   0.3   0.750
ABC  1-13-1990   1  0.4   0.4   1.500

【问题讨论】:

【参考方案1】:

您的 CTE 当前未定义为递归的,因为您认为递归的部分不是因为它不引用自身 - 所以它所做的只是一个普通的联合查询(所以你会得到更多的行,让你思考它是递归的,当它只是一个联合时)

http://msdn.microsoft.com/en-us/library/ms186243.aspx

WITH NewData (field1,field2,field3,field4,field5,field6) AS        
(    
SELECT  m.field1,m.field2,m.field3,m.field4,m.field5,m.field6    
FROM    MyTable as m    
WHERE m.field1 is not null            
GROUP BY m.field1,m.field2,m.field3,m.field4,m.field5,m.field6          
UNION ALL            
SELECT  m.field1, DATEADD(d, 1, m.field2), m.field3, m.field4, m.field5, m.field6       
FROM MyTable as m 
INNER JOIN NewData n on n.field1 = m.field1   
)

我不完全确定您要递归的连接条件,所以刚刚在代码示例中使用了 field1,但基本上使用该连接来定义行的关联方式。

【讨论】:

感谢您的回复。我正在尝试从 smalldatetime 字段(field2)中递归。我想获取第 1 行的日期,第 2 行的日期,并递归地将一天添加到第 1 行插入一行,直到我到达第 2 行中的日期。一旦到达第 2 行中的日期,CTE 应该移动到来自初始数据集的第 2 行和第 3 行......等等 这不太行得通,就递归而言,必须命中实际行,而不是在两者之间创建行。如果您有一个预先构建的日历表(如数字表),那么您可以破解它来工作。

以上是关于CTE 不经过递归的主要内容,如果未能解决你的问题,请参考以下文章

递归 CTE 性能不佳

将 SQL Server 中的递归 CTE 转换为 netezza

Impala SQL:合并具有重叠日期的行。不支持 WHERE EXISTS 和递归 CTE

锚和递归查询“CTE”列“ColumnName”中的递归部分之间的类型不匹配

递归 CTE 如何逐行运行?

SQL Server 公用表表达式(CTE)实现递归