在这个sqlfiddle ......
http://sqlfiddle.com/#!6/b6587/6
我收到以下错误....
声明终止。最大递归100已经用尽 在声明完成之前。
据我所知,CTE第二次选择的where子句需要进行“终止检查”。即使您取消注释WHERE子句,我也会得到相同的错误。
我只是想了解1)为什么需要它...毕竟每个订单行都与每个客户行有关系,并且2)因为需要“终止检查”才能获得什么这个例子可以工作。
顺便说一下,我想看到的查询输出如下。
1,'George', 'Patton','',''
1,'','','<some date>', 'tank'
1,'','','<some date>', 'plane'
2,'Lewie', 'Puller','',''
2,'','','<some date>', 'Rifle'
2,'','','<some date>', 'Hand Grenade'
顺便说一句,随意评论获得此类结果的其他方法(不使用递归cte),但也不使用游标或临时表。我想用基于集合的操作来做这件事。
修改
为了记录,我知道加入会起作用,但我有理由询问递归。为了给你上下文,我正在处理一个EXPORT文件的结果集。每行只有一列名为LINE。此外,导出文件需要按照我的示例的顺序输出...详细信息需要在标题行下,并且该模式需要重复...标题/详细信息...标题/详细信息。我认为也许递归可以解决这个问题。但是我知道简单连接也可以解决它,只要我能够将行输入正确的顺序...标题/细节...标题/细节,也许通过某种方式来做一个列来排序数字输出到正确的方式。
我的导出不依赖于调用应用程序来格式化数据...存储过程需要格式化数据。
答案 0 :(得分:1)
这是使用日期的更好示例。假设我们想要建立一个日期表。 2017年每月1行。我们创建一个@startDate
作为锚点,@endDate
作为终结符。我们将这些设置为相隔12个月,因为我们需要一年。然后,递归将通过DATEADD
函数将一个月添加到@startDate
,直到WHERE
子句中的终止符合为止。我们知道将需要11次递归才能达到12个月......也就是11个月+开始日期。如果我们将MAXRECURSION
设置为小于11的任何值,那么它将失败,因为需要11来实现递归WHERE
中的CTE
子句,即终止符。
declare @startDate datetime = '20170101'
declare @endDate datetime = '20171201'
;WITH Months
as
(
SELECT @startDate as TheDate --anchor
UNION ALL
SELECT DATEADD(month, 1, TheDate) --recursive
FROM Months
WHERE TheDate < @endDate --terminator... i.e. continue until this condition is met
)
SELECT * FROM Months OPTION (MAXRECURSION 10) --change this to 11
对于您的查询,简单的连接就足够了。
select
firstName
,lastName
,orderDate
,productID
from
customers c
inner join
orders o on o.customerID = c.id
但是,我发现你试图以奇怪的格式返回它,这应该在你正在使用的报告应用程序中处理。这会让你在没有递归的情况下接近。
with cte as(
select
firstName
,lastName
,orderDate
,productID
,dense_rank() over(order by c.id) as RN
from
customers c
inner join
orders o on o.customerID = c.id)
select distinct
firstName
,lastName
,null
,null
,RN
from
cte
union all
select
''
,''
,orderDate
,productID
,RN
from
cte
order by RN, firstName desc