目前實現方法有:
- 通過系統表master..spt_values獲取
- 用WHILE循環獲取
- 游標獲取
- CTE遞歸(感謝博友提供)
方法一:通過系統表master..spt_values獲取
1、獲取連續的日
-- 獲取連續區間的日期 DECLARE @StartTime DATE = '2019-03-08', -- 開始時間 @EndTime DATE = '2019-03-18' -- 結束時間 SELECT CONVERT(NVARCHAR(10),DATEADD(DAY,number,@StartTime),120) AS DayTime FROM master..spt_values WHERE type = 'p' AND number <= DATEDIFF(DAY,@StartTime,@EndTime)
2、獲取連續的月
-- 獲取連續區間的月份 DECLARE @StartTime DATE = '2019-03-08', -- 開始時間 @EndTime DATE = '2019-12-28' -- 結束時間 SELECT CONVERT(VARCHAR(7),DATEADD(MONTH,number,@StartTime),120) AS MonthTime FROM master..spt_values WITH (NOLOCK) WHERE type='P' AND number <= DATEDIFF(MONTH,@StartTime,@EndTime)
3、獲取連續的年
-- 獲取連續區間的年份 DECLARE @StartTime DATE = '2019-03-08', -- 開始時間 @EndTime DATE = '2020-03-08' -- 結束時間 SELECT CONVERT(VARCHAR(4),DATEADD(YEAR,number,@StartTime),120) AS YearTime FROM master..spt_values WITH (NOLOCK) WHERE type='P' AND number <= DATEDIFF(YEAR,@StartTime,@EndTime)
master..spt_values原理:
通過number來實現年月日的加減,因為number值最大是2047,所以只能連續加2047。
如圖:結束時間是'2026-03-28',但我們降序可以看到,從2019-03-08只能增加連續2047天,如此2024-10-24之后的日期就沒有了。
所以如果連續區間超過了2048,則此方法不適用,此時可以用以下方法二來實現
方法二:用WHILE循環獲取
1、獲取連續的日
-- 連續獲取天 DECLARE @StartTime DATE = '2019-03-08', -- 開始時間 @EndTime DATE = '2019-03-18' -- 結束時間 -- 創建臨時表#DateTime存儲日期 CREATE TABLE #DateTime ( DayTime DATE ); -- 循環獲取日期插入臨時表 WHILE @StartTime <= @EndTime BEGIN INSERT INTO #DateTime (DayTime) VALUES (@StartTime); SET @StartTime = DATEADD(DAY, 1, @StartTime); END; SELECT DayTime FROM #DateTime; -- 刪除臨時表 DROP TABLE #DateTime;
2、獲取連續的月
-- 連續獲取的月 DECLARE @StartTime DATE = '2019-03-08', -- 開始時間 @EndTime DATE = '2019-12-28' -- 結束時間 -- 創建臨時表#MonthTime存儲日期 CREATE TABLE #MonthTime ( MonthTime VARCHAR(7) ); -- 循環獲取日期插入臨時表 WHILE @StartTime <= @EndTime BEGIN INSERT INTO #MonthTime (MonthTime) VALUES (CONVERT(VARCHAR(7),@StartTime)); SET @StartTime = DATEADD(MONTH, 1, @StartTime); END; SELECT MonthTime FROM #MonthTime; -- 刪除臨時表 DROP TABLE #MonthTime;
3、獲取連續的年
-- 連續獲取的月 DECLARE @StartTime DATE = '2019-03-08', -- 開始時間 @EndTime DATE = '2025-03-28' -- 結束時間 -- 創建臨時表#YearTime存儲日期 CREATE TABLE #YearTime ( YearTime VARCHAR(4) ); -- 循環獲取日期插入臨時表 WHILE @StartTime <= @EndTime BEGIN INSERT INTO #YearTime (YearTime) VALUES (CONVERT(VARCHAR(4),@StartTime)); SET @StartTime = DATEADD(YEAR, 1, @StartTime); END; SELECT YearTime FROM #YearTime; -- 刪除臨時表 DROP TABLE #YearTime;
方法三:用游標獲取,原理和WHILE循環相似,此處不再展示
方法四:評論區博友說的CTE遞歸
DECLARE @StartTime DATE = '2018-12-08', -- 開始時間 @EndTime DATE = '2019-03-18' -- 結束時間 ; -- 獲取連續天 WITH CteDateDay AS ( SELECT @StartTime DayTime UNION ALL SELECT DATEADD(DAY,1,DayTime) DayTime FROM CteDateDay WHERE DayTime<@EndTime ) SELECT DayTime FROM CteDateDay OPTION (MAXRECURSION 0) ; -- 獲取連續月 WITH CteDateMonth AS ( SELECT CONVERT(VARCHAR(7),@StartTime,120) MonthTime UNION ALL SELECT CONVERT(VARCHAR(7),DATEADD(MONTH,1,CAST(MonthTime+'-01' AS DATE)),120) DayTime FROM CteDateMonth WHERE MonthTime<CONVERT(VARCHAR(7),@EndTime,120) ) SELECT MonthTime FROM CteDateMonth OPTION (MAXRECURSION 0) ; -- 獲取連續年 WITH CteDateYear AS ( SELECT DATEPART(YEAR,@StartTime) YearTime UNION ALL SELECT YearTime+1 DayTime FROM CteDateYear WHERE YearTime<DATEPART(YEAR,@EndTime) ) SELECT YearTime FROM CteDateYear OPTION (MAXRECURSION 0)
如果有什么好的方法和建議,歡迎大家來指點,謝謝!