If input is provided like below
declare @from datetime = '2016-09-15'
declare @to datetime = '2016-12-25'
Then output should be like below
Month Start_date End_date
September 2016-09-15 2016-09-30
October 2016-10-01 2016-10-31
November 2016-11-01 2016-11-30
December 2016-12-01 2016-12-25
If input is provided like this:
declare @from datetime = '2016-12-05'
declare @to datetime = '2016-12-25'
Then output should be like this:
Month Start_date End_date
December 2016-12-05 2016-12-25
Thanks in advance.
Try this, I hope this helps.
DECLARE @fromDate DATE = '2016-09-05', @toDate DATE = '2016-12-25', @tempStartDate DATE
DECLARE @tempTable TABLE(Month NVARCHAR(50), Start_Date DATE, End_Date DATE)
SELECT @tempStartDate = @fromDate
WHILE(CAST(@tempStartDate AS DATE) <= CAST(@toDate AS DATE))
BEGIN
INSERT INTO @tempTable
SELECT DATENAME(MONTH, @tempStartDate),@tempStartDate,
CASE WHEN DATEPART(MONTH,@tempStartDate) = DATEPART(MONTH,@toDate) THEN @toDate ELSE DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@tempStartDate)+1,0)) END
SET @tempStartDate = DATEADD(s,1,DATEADD(mm, DATEDIFF(m,0,@tempStartDate)+1,0))
END
SELECT * FROM @tempTable
You can do this with an ad-hoc tally table. Using spt_values, but any larger table will do.
Furthermore, this approach would be faster than a recursive cte, especially for larger sets
declare @from date = '2016-09-15'
declare @to date = '2016-12-25'
Select Month = max(DateName(MONTH,D))
,Start_date = min(D)
,End_date = max(D)
From (Select Top (DateDiff(DD,@from,@to)+1) D=DateAdd(DD,Row_Number() Over (Order By (Select null))-1,@from) From master..spt_values ) A
Group By Year(D),Month(D)
Order By min(d)
Returns
Month Start_date End_date
September 2016-09-15 2016-09-30
October 2016-10-01 2016-10-31
November 2016-11-01 2016-11-30
December 2016-12-01 2016-12-25
Edit - As Requested
The process is really not that complicated. We use Row_Number() in concert with DateAdd() to generate a list of dates within the specified date range.
The sub-query produces the following
D
2016-09-15
2016-09-16
2016-09-17
2016-09-18
2016-09-19
2016-09-20
2016-09-21
2016-09-22
2016-09-23
...
2016-12-20
2016-12-21
2016-12-22
2016-12-23
2016-12-24
2016-12-25
Then it becomes a simple matter of getting the min/max dates by year/month.
Again, I used master..spt_values
, but virtually any table would do. If you don't have a tally/numbers table, I would strongly recommend one.
It can be accomplished with a recursive CTE
declare @from datetime = '2016-09-15'
declare @to datetime = '2016-12-25'
;with cte_r
AS
(
SELECT
@from AS Dte1
,@to AS Dte2
,DATEADD(MM,DATEDIFF(MM,0,@from),0) AS MonthStrt
,DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,0,@from)+1,0)) AS MonthEnd
UNION ALL
SELECT
@from AS Dte1
,@to AS Dte2
,DATEADD(MM,1,MonthStrt)
,DATEADD(MM,1,MonthEnd)
FROM
cte_r
WHERE
MonthEnd <= @to
)
SELECT
CASE WHEN MonthStrt <= @from THEN @from ELSE MonthStrt END AS Stat_Date
,CASE WHEN MonthEnd >= @to THEN @to ELSE MonthEnd END AS End_Date
FROM
cte_r
declare @from date = '2016-09-15'
declare @to date = '2016-12-25';
with cte as
(select datename(month,@from )as month1,1 as n , @from as startdate,eomonth(@from)as endate
union all
select datename(month,dateadd(day,n,@from)),n+1,dateadd(day,n,@from),eomonth(dateadd(day,n,@from))
from cte where dateadd(day,n,@from)<@to
)select month1,min(startdate),max(endate) from cte
group by month1
order by 1 desc
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.