Sql 如何根据日期以一个月为增量填充表格

Sql 如何根据日期以一个月为增量填充表格,sql,sql-server,date,variables,datediff,Sql,Sql Server,Date,Variables,Datediff,我需要根据另一个表的输入日期加载一个表,输入日期介于一个月的第一天和该月的最后一天之间。我需要将负载减少为1个月的记录值,从当前月份开始减少1个月,然后从当前月份开始减少2个月,依此类推 我尝试过CTE,使用光标,手动更改datediff参数。最后一种方法有效,但我希望动态加载表 Declare @StartDt as datetime = (SELECT FORMAT(DATEADD(s,0,DATEADD(mm, DATEDIFF(m,0,GETDATE())-1,0)),'MM/dd/yy

我需要根据另一个表的输入日期加载一个表,输入日期介于一个月的第一天和该月的最后一天之间。我需要将负载减少为1个月的记录值,从当前月份开始减少1个月,然后从当前月份开始减少2个月,依此类推

我尝试过CTE,使用光标,手动更改datediff参数。最后一种方法有效,但我希望动态加载表

Declare @StartDt as datetime = (SELECT FORMAT(DATEADD(s,0,DATEADD(mm, DATEDIFF(m,0,GETDATE())-1,0)),'MM/dd/yyyy'));

Declare @endDt as datetime = EOMONTH(@StartDt);

SELECT  useruid, 
    userfullname,
    sum(totaltime)SumTime,
    @StartDt as StartDate, 
    @EndDt as EndDate

FROM Table_1.tbl
WHERE ENTRYDATE between @StartDt  and @EndDt
group by useruid, USERFULLNAME;
我正在把这个插入另一个表中。通过手动将Startdt变量中的-1更改为-2,依此类推,这样做并没有问题。我想知道是否可以在加载另一个表时动态更改它


同样,我在加载表时没有问题。我只想知道是否有更有效的方法来实现这一点,因为我必须回到100个月前。

您可以使用动态SQL动态编写@StartDt declare语句

我将您的代码放入while循环,该循环将运行100次。追溯到100个月前:

declare @int int = 0
while @int > -100
begin
set @int= @int -1
declare @str varchar(max)
set @str = 'declare @StartDt as datetime = (SELECT FORMAT(DATEADD(s,0,DATEADD(mm, DATEDIFF(m,0,GETDATE())'+cast(@int as varchar(10))+',0)),''MM/dd/yyyy''))'
execute (@str)

Declare @endDt as datetime = EOMONTH(@StartDt)

SELECT  useruid, 
    userfullname,
    sum(totaltime)SumTime,
    @StartDt as StartDate, 
    @EndDt as EndDate

FROM Table_1.tbl
WHERE ENTRYDATE between @StartDt  and @EndDt
group by useruid, USERFULLNAME
end

一种方法是递归CTE:

with dates as (
      select datefromparts(year(getdate()), month(getdate()), 1) as dte
      union all
      select dateadd(month, -1, dte)
      from dates
      where dte > ?  -- how far back do you want to go?
     )
select t.useruid, t.userfullname, sum(t.totaltime) as SumTime,
       d.dte as StartDate, 
       dateadd(month, 1, d.dte) as EndDate
from dates d JOIN
     Table_1.tbl t
     on t.ENTRYDATE >= d.dte AND
        t.ENTRYDATE < dateadd(month, 1, d.dte) 
group by t.useruid, t.USERFULLNAME, d.dte;
您不需要显式循环或游标


注意:出于某种原因,您似乎在从日期中减去一秒钟。我不明白为什么。对于结束日期,您可能需要这种逻辑,但最好使用on子句中的不等式,这样您就不必担心毫秒了。

我不明白-您正在筛选月份中的哪一天,然后一次返回一个月,但插入到同一个表中。为什么你不能一次加载所有的100个月呢?非常感谢戈登,这很有效。我想我知道我的CTE哪里出了问题。我只需要做一个小小的调整。当前的结束日期为下个月的第一天。我需要结束日期是开始日期月份的最后一天。我将dateaddmonth,1,d.dte更改为EndDate,将EOMONTHdte更改为EndDate。这没有任何意义-您似乎不需要在该范围内的每个月都使用它,您通过它实现了什么,而不仅仅是过滤100个月的范围?@mcedave。你不接受这个答案有什么原因吗?这对我来说似乎是最好的解决办法。也谢谢你,万根,我得到了你的建议well@mcedave不客气。递归CTE解决方案比我的要好得多。这就是为什么我投票支持戈登的答案。但我希望我的解决方案能给你一些新的想法。