Tsql 两个日期之间的年和月的T-SQL列表

Tsql 两个日期之间的年和月的T-SQL列表,tsql,Tsql,我有一个表,其中列出了有生效日期和终止日期的个人名单。 示例人员1,20171201,20180601 对于每一条记录,我需要输出一个列表,列出它们在这两个日期之间“活跃”的年份和月份。 所以输出看起来像 这是在SQL Server 2016中 任何帮助都将不胜感激 根据你提供的信息,我做了一些猜测。也许递归CTE将有助于: DECLARE @tab TABLE (Person INT, EffectiveDate DATE, TerminationDate DATE) INSERT @tab

我有一个表,其中列出了有生效日期和终止日期的个人名单。 示例人员1,20171201,20180601 对于每一条记录,我需要输出一个列表,列出它们在这两个日期之间“活跃”的年份和月份。 所以输出看起来像

这是在SQL Server 2016中
任何帮助都将不胜感激

根据你提供的信息,我做了一些猜测。也许递归CTE将有助于:

DECLARE @tab TABLE (Person INT, EffectiveDate DATE, TerminationDate DATE)
INSERT @tab VALUES
(1, '2017-12-01', '2018-05-31'),
(2, '2017-10-01', '2018-01-01'),
(3, '2018-02-01', '2018-12-01')

;WITH t AS (
    SELECT Person, EffectiveDate AS Dt
    FROM @tab
    UNION ALL
    SELECT Person, DATEADD(mm,1,Dt)
    FROM t
    WHERE t.Dt < (SELECT DATEADD(mm,-1,TerminationDate) FROM @tab tt WHERE tt.Person = t.Person)
    )

SELECT *
FROM t
ORDER BY Dt

欢迎来到stackoverflow!为了获得更好的帮助,最好包含DDL易于使用的示例数据,我们可以使用这些数据快速重新创建您正在做的事情并提供解决方案。请注意以下示例数据:

DECLARE @yourtable TABLE(person VARCHAR(20), date1 DATE, date2 DATE)
INSERT @yourtable (person, date1, date2) 
VALUES ('Person1','20171201', '20180601'), ('Person2','20171001', '20180101'),
       ('Person3','20180101', '20180301');

SELECT t.* FROM @yourtable AS t;
返回:

person               date1      date2
-------------------- ---------- ----------
Person1              2017-12-01 2018-06-01
Person2              2017-10-01 2018-01-01
Person3              2018-01-01 2018-03-01
Person               ActiveYear  ActiveMonth
-------------------- ----------- -----------
Person1              2017        12
Person1              2018        1
Person1              2018        2
Person1              2018        3
Person1              2018        4
Person1              2018        5
Person2              2017        10
Person2              2017        11
Person2              2017        12
Person3              2018        1
Person3              2018        2
(我加了几行)。以下是我的解决方案:

DECLARE @yourtable TABLE(person VARCHAR(20), date1 DATE, date2 DATE)
INSERT @yourtable (person, date1, date2) 
VALUES ('Person1','20171201', '20180601'), ('Person2','20171001', '20180101'),
       ('Person3','20180101', '20180301');

SELECT 
  Person      = t.person,
    ActiveYear  = YEAR(st.DT),
  ActiveMonth = MONTH(st.Dt)
FROM   @yourtable AS t
CROSS APPLY
(
  SELECT TOP (DATEDIFF(MONTH,t.date1,t.date2)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
  FROM       (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS a(x)
  CROSS JOIN (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS b(x)
) AS iTally(N)
CROSS APPLY (VALUES(DATEADD(MONTH, iTally.N-1, t.date1))) AS st(Dt);
返回:

person               date1      date2
-------------------- ---------- ----------
Person1              2017-12-01 2018-06-01
Person2              2017-10-01 2018-01-01
Person3              2018-01-01 2018-03-01
Person               ActiveYear  ActiveMonth
-------------------- ----------- -----------
Person1              2017        12
Person1              2018        1
Person1              2018        2
Person1              2018        3
Person1              2018        4
Person1              2018        5
Person2              2017        10
Person2              2017        11
Person2              2017        12
Person3              2018        1
Person3              2018        2

如果你有问题,请告诉我

只是因为我没有看到它被提供。下面是另一种使用临时日历表的方法

请注意基准日期为2000-01-01和10000天。。。如果需要,可以扩大或缩小

示例

Declare @YourTable table (Person int,startdate date,  enddate date)
Insert Into @YourTable values 
(1,'20171201','20180601')

Select Distinct 
       A.Person
      ,ActiveYear = year(D)
      ,ActiveMonth = month(D)
From  @YourTable A
Join  (
          Select Top 10000 D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),'2000-01-01') 
                From  master..spt_values n1,master..spt_values n2
      ) B on D between startdate and enddate
返回

Person  ActiveYear  ActiveMonth
1       2017        12
1       2018        1
1       2018        2
1       2018        3
1       2018        4
1       2018        5
1       2018        6

你试过什么了吗?记住,这是一个帮助克服困难的论坛,而不是一个解决家庭作业的论坛。顺便说一句,截图上写着“person1,person2,等等”,我想这是不对的,对吧?是否应排除“截止”日期?最后,这种逻辑通常属于应用程序而不是数据库。这真的必须在SQL级别完成吗?@Andrew是的,我已经尝试了一些我找到的示例,但是没有任何东西可以让我获得我想要的输出。您在图片中的回答是正确的。您的回答是正确的。图片中的回答是错误的,应在每个活动年/月重复(已更正)回答您的上一个问题。是的,这需要在SQL级别完成,因为上面没有应用程序。您好,欢迎使用stackoverflow。请避免发布数据或代码的图片。。。特别是当需要剪切/粘贴的信息量如此之小时,例如在您的问题中。我们无法回答此问题。您需要向我们展示完整的数据模型(作为输入)和预期的输出。您尚未显示输入。对于任何可能的输入,都有任何可能的代码来创建您描述的输出。请发布源表的完整DDL。另外,发布任何您期望可以工作的代码,但它并没有达到您期望的效果。我建议使用日期表或计数。对于基本计数,递归CTE的性能将非常糟糕。请注意这篇文章详细介绍了这个问题:非常感谢您的示例。我正在查看table变量,只是无法获得正确的语法,可能应该发布它。我拿你的例子,和我的比较,发现了我的错误。现在的问题是,我现在遇到了一个“最大递归100在语句完成之前已耗尽”错误。有些日期之间有相当长的距离。我会在我这边做更多的研究。再次感谢你的回答。我想这会让我接近我想要的!