2013-02-25 164 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天。

相關問題