当前位置: 首页 > 面试题库 >

了解递归CTE终止检查

白才捷
2023-03-14
问题内容

在这个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。此外,导出文件需要按照我的示例顺序输出…详细信息需要在标题行下,并且该模式需要重复…
header / details … header /
details。我认为也许递归可以解决这个问题。但是我知道简单的联接也可以解决问题,只要我可以使行按正确的顺序…标题/详细信息…标题/详细信息,也许可以通过某种方式对以数字排序的列进行输出正确的方式。

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


问题答案:

这是一个使用日期的更好示例。假设我们要建立一个日期表。2017年的每个月有1行。我们创建一个@startDate作为锚点和@endDate终止点。我们希望将这些时间间隔为12个月,因为我们希望使用一年。然后,递归将通过DATEADD函数添加一个月到,@startDate直到WHERE子句中的终止符得到满足。我们知道需要12次递归才能达到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


 类似资料:
  • 问题内容: 我在数据库中存储了一组依赖项。我正在寻找直接或间接依赖于当前对象的所有对象。由于对象可以依赖零个或多个其他对象,因此完全可以合理地认为对象1被对象9两次依赖(9依赖于4和5,这两个都依赖于1)。我想获取不依赖复制的所有依赖于当前对象的对象的列表。 如果存在循环,这将变得更加复杂。没有循环,一个人可以使用DISTINCT,尽管多次经过长链仅在末尾剔除它们仍然是一个问题。但是,对于循环,重

  • 问题内容: 考虑以下简单的DAG: 现在想象一下,我还有其他一些任意准则选择第一个和最后一个边缘,即1-> 2和3-> 4。我想使用这些来查找图表的其余部分。 我可以编写一个递归CTE,如下所示(我使用的是MSDN的术语): 但是,这导致边缘3-> 4被两次选择: 如何防止查询重复出现在已经描述过的子图中?如果在查询的“递归成员”部分中,我可以引用 到目前为止递归CTE检索到的所有数据 (并在递归

  • 我试图写一个程序,找出给定的数字是否在斐波那契序列中,我不断得到不终止的递归,我不知道为什么。第17行似乎是个大问题。当我输入0或1时,我会得到想要的答案。我只是在寻找答案,我正在努力学习,所以仅仅告诉我答案对我没有多大帮助。

  • 问题内容: 我正在尝试执行我认为使用CTE进行递归比较困难的事情是SQL Server 2008。 在下面的示例中,您可以假设固定深度为3 …没有任何比这更低的深度了。在现实生活中,深度是“更深的”,但仍然是固定的。在示例中,我尝试将其简化一些。 我的输入数据如下。 我的CTE的输出应为下表。 如果我可以在输出中获得ID列,则可以肯定地可以映射到查找表中的名称。 我也乐于接受其他方法来完成此任务,

  • 问题内容: 假设具有以下CTE,这些CTE返回我已经拥有的某些树数据(邻接模型)的级别(取自Linq中的分层数据- options和performance): 我想知道通过使用C#而不是SQL进行递归是否会提高性能。假设我有一个IQueryable,其中Tree是表示层次结构表中条目的实体,谁能向我展示如何执行CTE与递归C#函数相同的工作?类似于以下内容: 看到使用lambda表达式很容易做到这

  • 问题内容: 此查询生成从1到4的数字。 但是,如果我对此进行修改, 它给 错误:“ z”处或附近的语法错误 我在这里做错了什么? 问题答案: 我认为这是因为RECURSIVE是WITH语句的修饰符,而不是常用表表达式的属性,因此您可以像这样使用它: