2013-02-25 124 views
2

我有以下函数应该返回两个月之间的月份的开始和结束日期,但问题是如何,因为这个月是28天,函数计算28天的所有即将到来的月份从而返回以下错误值。获取SQL中两个日期之间月份的开始和结束日期?

StartDate EndDate 
----------------------- 
2013-02-01 2013-02-28 
2013-03-01 2013-03-28 
2013-04-01 2013-04-28 



declare @sDate datetime, 
     @eDate datetime; 

select @sDate = '2013-02-25', 
     @eDate = '2013-04-25'; 

;with months as 
(
    select DATEADD(mm,DATEDIFF(mm,0,@sDate),0) StartDate, 
    DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@sDate)+1,0)) EndDate 

    union all 
    select dateadd(mm, 1, StartDate), 
    dateadd(mm, 1, EndDate) 
    from months 
    where dateadd(mm, 1, StartDate)<= @eDate 
) 

select * from months 

我该如何修改这个返回正确的日期?

+0

你不应该用包容上限 - 你应该说“不到下个月开始”。这是考虑日期/时间/时间戳记值的错误方法,[显然SQL Server有一组独特的问题](http://sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/what-do在处理这个问题时也是如此 - 在-and-the-devil-have-in-common.aspx中)。因此,获取本月的开始,添加一个月,并使用包含下限('> =')和独占上限('<')。 – 2013-02-25 18:21:54

回答

6

试试这个;

declare @sDate datetime, 
     @eDate datetime 

select @sDate = '2013-02-25', 
     @eDate = '2013-04-25' 

;with cte as (
    select convert(date,left(convert(varchar,@sdate,112),6) + '01') startDate, 
     month(@sdate) n 
    union all 
    select dateadd(month,n,convert(date,convert(varchar,year(@sdate)) + '0101')) startDate, 
     (n+1) n 
    from cte 
    where n < month(@sdate) + datediff(month,@sdate,@edate) 
) 
select startdate, dateadd(day,-1,dateadd(month,1,startdate)) enddate 
from cte 

FIDDLE DEMO

| STARTDATE | ENDDATE | 
--------------------------- 
| 2013-02-01 | 2013-02-28 | 
| 2013-03-01 | 2013-03-31 | 
| 2013-04-01 | 2013-04-30 | 
+0

你可以评论的代码,并解释它在做什么,谢谢 – Xerxes 2013-02-25 22:20:40

+0

在边cte,它得到的给定日期之间的每个月的startdates,然后out cte,我使用startdate找到同一个月的结束日期使用dateadd功能。即使你在两年内给出日期,这也是有效的。玩小提琴你会明白。 – Kaf 2013-02-25 22:33:50

1

如果您可以得到本月的第一天,请使用dateadd两次获取最后一天。

首先,加1个月,然后减1天。

相关问题