0

在这种sqlfiddle ...了解递归CTE终止检查

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)的其他方式来获得这种结果发表评论,但还没有使用游标或临时表。我想用基于集合的操作来做到这一点。

编辑

为了记录在案,我知道参加的工作,但我有问递归的理由。为了给你上下文,我正在处理一个导出文件的结果集。每行只有一列称为LINE。此外,导出文件需要按照我的示例的顺序输出...细节需要在标题行下面,该模式需要重复...标题/细节...标题/细节。我认为递归可以解决这个问题。但我知道简单的连接也可以解决它,只要我可以得到行正确的顺序...头/细节...头/细节,也许有一些方法来做一个列排序数字的输出正确的方式。

我的导出不会依赖于调用应用程序来格式化数据......存储过程需要格式化数据。

+2

你为什么在这里使用递归? IT将无休止地循环查找相同的客户编号,一遍又一遍地重复查看订单表。看起来像一个简单的连接会做你正在做的任何事情,因为这个数据没有层次关系。查看[这个sqlfiddle](http://sqlfiddle.com/#!6/b6587/9)使用“深度”来跟踪递归步骤并将递归限制为20. – JNevill

+0

它会超过递归的最大数量,它默认情况下是100.这是由于你有一个查询问题 - 这是一个无限的递归,因为@JNevill声明 – scsimon

+0

任何反馈seth? – scsimon

回答

1

下面是使用日期的更好示例。假设我们想建立一个日期表。 2017年每月1行。我们创建一个@startDate作为锚点,@endDate作为终结点。我们将这些设置为12个月,因为我们想要一年。然后,递归将通过DATEADD函数向@startDate添加一个月,直到在WHERE子句中满足终止符。我们知道这需要11次递归才能达到12个月......也就是11个月+开始日期。如果我们设置MAXRECURSION以任何低于11,则自11需要履行我们的递归CTEWHERE子句就会失败,这是终结者..

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 
+0

,看着我的sqlfiddle,你能按照我要求的顺序来获得sql小提琴吗?你的联盟会返回所有的“标题”,然后返回所有的“细节”。 ORDER在这个问题中确实是一件很有意义的事情... header/details ... header/details。我认为递归“可能”解决了这个问题。 –

+0

我很困惑@SethSpearman。我与工会的联合会返回您的确切结果。 – scsimon

+0

对不起,我正在寻找小提琴。上面评论中的那个不是你的,我没有注意到......但是确定你的代码确实工作。这里是一个小提琴... http://sqlfiddle.com/#!6/b6587/36 –