i want to get months between two dates with their starting and end dates.Suppose if i enter startdate as \"2017-04-01\" and enddate as \"2017-07-31\", i want list of months
Without recursion, using master.dbo.spt_values
as a substitute for a numbers table:
declare @StartDate date = '20170401'
, @EndDate date = '20170731';
;with Months as (
select top (datediff(month,@startdate,@enddate)+1)
[Month] = dateadd(month, row_number() over (order by number) -1, @StartDate)
, MonthEnd = dateadd(day,-1,dateadd(month, row_number() over (order by number), @StartDate))
from master.dbo.spt_values
order by [Month]
)
select * from Months;
rextester demo: http://rextester.com/FXQJ4048
returns:
+------------+------------+
| Month | MonthEnd |
+------------+------------+
| 2017-04-01 | 2017-04-30 |
| 2017-05-01 | 2017-05-31 |
| 2017-06-01 | 2017-06-30 |
| 2017-07-01 | 2017-07-31 |
+------------+------------+
When generating a set or sequence in SQL Server, methods that avoid recursion and loops perform significantly better as the number of values increases.
Reference:
To get the start and end dates of each month within a given range, when the value of the @StartDate
parameter is not the first day of the month:
The first option is to truncate the @StartDate
parameter to the first of the month, the second option is to adjust the expressions in the common table expression to truncate the values there:
declare @StartDate date = '20170415'
, @EndDate date = '20170715';
/* Option 1: truncate @StartDate to the beginning of the month */
--set @StartDate = dateadd(month, datediff(month, 0, @StartDate), 0);
/* Option 2: Truncate @StartDate to month in the common table expression: */
;with Months as (
select top (datediff(month,@StartDate,@EndDate)+1)
[Month] = dateadd(month
, datediff(month, 0, @StartDate) + row_number() over (order by number) -1
, 0)
, MonthEnd = dateadd(day,-1,dateadd(month
, datediff(month, 0, @StartDate) + row_number() over (order by number)
,0))
from master.dbo.spt_values
order by [Month]
)
select * from Months;