表数据子集上的递归 CTE

Posted

技术标签:

【中文标题】表数据子集上的递归 CTE【英文标题】:Recursive CTE on Subset of Table Data 【发布时间】:2020-06-18 11:29:27 【问题描述】:

我目前有一个表格,其中每条记录都有一个开始日期和结束日期。我需要创建一个单独的表来显示所有记录以及开始日期和结束日期之间的月份和年份。

我创建了这个递归 CTE 查询来执行此操作,但它只返回我需要的子集中的一条记录。我的问题是如何编辑它,以便它在子集中的所有记录上运行递归 CTE。

declare @start DATE
declare @end DATE 
declare @Opportunity Nvarchar(20)

SELECT  @start=eststartdate, @end=estcompletiondate, @opportunity=opportunity from opportunity where status='A'

;with months (Opportunity,Date)
AS
(
    SELECT @opportunity as Opportunity, DATEADD(DAY,1,EOMONTH(@start,-1))
    UNION ALL
    SELECT @opportunity as Opportunity,DATEADD(month,1,date)
    from months
    where DATEADD(month,1,date) < EOMONTH(@end)
)
select Opportunity, Datename(month,date),Year(date)
from months

结果看起来像这样。

Opportunity1,  January, 2020
Opportunity1,  February, 2020
Opportunity1,  March, 2020
Opportunity2,  January, 2020
Opportunity2,  February, 2020
Opportunity2,  March, 2020

【问题讨论】:

这显然是 SQL Server,所以我添加了那个标签。显示您想要的结果。你的问题也没有提到OpportunityId,但这似乎很重要。我对你真正想要什么感到困惑。 【参考方案1】:

如果您想要每个机会的记录,那么您想要这样的东西:

with months as (
      select o.opportunity, eststartdate as startdate, estcompletiondate as enddate
      from opportunity o left join
           OpportunityCustomTabFields oc
           on o.opportunityid = oc.opportunityid
      where o.status = 'A' and oc.custSFID IS NULL
      union all
      select opportunity, dateadd(month, 1, startdate), enddate
      from months
      where startdate < enddate
     )
select m.*
from months;

关于你的问题,我不明白几件事。例如,您在问题中描述了一个表,但您的查询有多个表。您谈论日期,然后添加EOMONTH(),好像这很重要。

但是,以上内容应该与您想要的足够接近。您可能需要对其进行调整。如果您需要更多帮助,我建议您提出一个问题,并提供适当的样本数据、所需的结果和清晰的解释。

【讨论】:

我真的很感激。我从示例中删除了另一个表。这是一个更好地定义子集的连接。与我的问题无关,所以我把它拿出来了。 EOMONTH() 我之所以添加,是因为我看到了一些带有某些开始和结束日期的奇怪结果。我要试试这个,看看它是否有效。 就是这样。谢谢戈登。我需要将 where 子句改为 where DATEADD(month,1,startdate)

以上是关于表数据子集上的递归 CTE的主要内容,如果未能解决你的问题,请参考以下文章

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

SQL Server中公用表表达式(CTE)递归的生成帮助数据

MariaDB表表达式:CTE

通用表表达式

PostgreSQL递归查询示例

CTE 递归语句,带自连接,不带 id