我正在尝试获取当前月和最后两个月之间的所有日期。
例如:今天10-01-2019 使用sql脚本,我将获得2018年10月1日至2019年1月31日之间的所有日期。
with cte as
(
select getdate() as n
union all
select dateadd(DAY,-1,n) from cte where month(dateadd(dd,-1,n)) < month(DATEADD(month, -3, getdate())) --and month(DATEADD(month, 0, getdate()))
union all
select dateadd(DAY,-1,n) from cte where month(dateadd(dd,-1,n)) > month(DATEADD(month, 0, getdate()))
)
select * from cte
我知道
错误消息530,级别16,状态1,第1行 声明终止。语句完成之前,最大递归100已用尽。
答案 0 :(得分:5)
递归不是解决此问题的好方法。使用递归cte递增计数器的性能是与游标相同的事情。 http://www.sqlservercentral.com/articles/T-SQL/74118/
更好的方法是基于此集合。对于此任务,理货表是理想的。 Here是关于该主题的精彩文章。
我在系统中保留一个理货表格作为视图。读取速度为零,速度很快。
create View [dbo].[cteTally] as
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select N from cteTally
GO
然后对于这种问题,它使用起来超级简单。这样会产生相同的结果而不会循环。
declare @endDate datetime = '2019-01-31'
, @tmpDate datetime = '2018-10-01'
select dateadd(day, t.N - 1, @tmpDate)
from cteTally t
where t.N - 1 <= DATEDIFF(day, @tmpDate, @endDate)
-编辑-
如果您需要动态设置,可以使用一点日期数学。无论您何时运行,这都将获取3个月前到当月末的数据。如果您以前从未看过这种事情,那么日期逻辑可能会有点难以理解。 Lynn Pettis在这个主题上有一篇很棒的文章。 http://www.sqlservercentral.com/blogs/lynnpettis/2009/03/25/some-common-date-routines/
select dateadd(day, t.N - 1, dateadd(month, -3, dateadd(month, datediff(month, 0, getdate()), 0)))
from cteTally t
where t.N - 1 < datediff(day,dateadd(month, -3, dateadd(month, datediff(month, 0, getdate()), 0)), dateadd(month, datediff(month, 0, getdate()) + 1, 0))
答案 1 :(得分:4)
这将取决于您的SQL Server版本。
with cte as
(
select cast(getdate() as date) as n
union all
select dateadd(DAY,-1,n) from cte where dateadd(DAY,-1,n) > (select eomonth(cast(dateadd(month,-4,getdate()) as date)))
)
select *
from cte
order by n desc
option (maxrecursion 200)
答案 2 :(得分:2)
您正在达到最大递归限制。作为选择增加它:
with cte as
(
select getdate() as n
union all
select dateadd(DAY,-1,n) from cte where month(dateadd(dd,-1,n)) < month(DATEADD(month, -3, getdate())) --and month(DATEADD(month, 0, getdate()))
union all
select dateadd(DAY,-1,n) from cte where month(dateadd(dd,-1,n)) > month(DATEADD(month, 0, getdate()))
)
select * from cte
OPTION (MAXRECURSION 1000)
答案 3 :(得分:2)
您可以为此使用临时表。通过循环,只需将所需的日期添加到临时表即可。检查以下查询:
create table #temp (thedate date)
declare @i int = 1
declare @tmpDate datetime = dateadd(month,-2,getdate())
while @tmpDate<=getdate()
begin
insert into #temp
values (@tmpDate)
set @tmpDate = dateadd(day,1,@tmpDate)
end
select * from #temp
编辑:基于OP的评论,新查询:
create table #temp (thedate date)
declare @i int = 1
declare @endDate datetime = '2019-01-31'
declare @tmpDate datetime = '2018-10-01'
while @tmpDate<=@endDate
begin
insert into #temp
values (@tmpDate)
set @tmpDate = dateadd(day,1,@tmpDate)
end
select * from #temp
答案 4 :(得分:2)
with cte as
(
select dateadd(month,1,dateadd(day, -1* day(getdate()) , cast(getdate() as date) ) ) n
union all
select dateadd(day,-1,n) from cte where month(n) + year(n) * 12 >= month(getdate()) + year(getdate()) * 12 -3
),
final as (select * from cte except select top 1 * from cte order by n)
select * from final order by n
OPTION (MAXRECURSION 1000)
或仅使用dateadd并避免使用例外
with cte as
(
select dateadd(day,-1,dateadd(month,1,dateadd(day, 1 - day(getdate()) , cast(getdate() as date)))) n
union all
select dateadd(day,-1,n) from cte where n > dateadd(month,-3,dateadd(day , 1 - day(getdate()),cast(getdate() as date)))
)
select * from cte order by n
OPTION (MAXRECURSION 1000)
答案 5 :(得分:2)
如果您使用的是SQL 2012 +
[[], ['an', 'be'], [], ['king'], ['brave']]
对于早期版本的SQL:
SELECT
dateadd(dd, number, (dateadd(dd, 1, dateadd(MM, -4, eomonth(getdate()))))) as TheDate
FROM
master..spt_values m1
WHERE
type = 'P'
AND dateadd(dd, number, (dateadd(dd, 1, dateadd(MM, -4, eomonth(getdate())))) ) <= eomonth(getdate())