如果提供如下输入
declare @from datetime = '2016-09-15'
declare @to datetime = '2016-12-25'
然后输出应该如下
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
如果提供如下输入:
declare @from datetime = '2016-12-05'
declare @to datetime = '2016-12-25'
然后输出应该是这样的:
Month Start_date End_date
December 2016-12-05 2016-12-25
提前致谢。
答案 0 :(得分:1)
试试这个,我希望这有帮助。
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
答案 1 :(得分:1)
您可以使用临时计数表执行此操作。使用spt_values,但任何更大的表都可以。
此外,这种方法比递归cte更快,特别是对于更大的集合
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)
返回
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
修改 - 按要求
这个过程真的不那么复杂。我们与DateAdd()一起使用Row_Number()来生成指定日期范围内的日期列表。
子查询产生以下
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
然后,根据年/月获得最小/最大日期变得简单。
同样,我使用master..spt_values
,但实际上任何表都可以。如果你没有理货/数字表,我强烈推荐一个。
答案 2 :(得分:0)
可以使用递归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
答案 3 :(得分:0)
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