如果我有一个开始和结束日期,然后是一个单独的开始和结束时间,我想返回日期范围内每个日期的时间范围。
这是一个小例子: 我将以下变量设置为以下示例值:
declare @StartDate date
declare @EndDate date
declare @StartTime time
declare @EndTime time
declare @interval int = 10
set @StartDate = '2017-08-23'
set @EndDate = '2017-08-25'
set @StartTime = '07:00:00'
set @EndTime = '07:30:00'
我想要返回的内容如下:
column1
2017-08-23 07:00:00.000
2017-08-23 07:10:00.000
2017-08-23 07:20:00.000
2017-08-23 07:30:00.000
2017-08-24 07:00:00.000
2017-08-24 07:10:00.000
2017-08-24 07:20:00.000
....
等。直到最终的日期时间值。
我已经提出了一个有效的解决方案(可能对某些人有所帮助),但我觉得应该有更优雅的方法来达到相同的效果。
这是我的解决方案:
;
WITH DateCTE
AS(
Select @StartDate as StartDate
UNION ALL
SELECT DATEADD(DAY,1,StartDate)
FROM DateCTE
WHERE DATEADD(DAY,1,StartDate) <= @EndDate
)
, TimeCTE
AS(
Select @StartTime as StartTime
UNION ALL
SELECT DATEADD(MINUTE,@interval,StartTime)
FROM TimeCTE
WHERE DATEADD(MINUTE,@interval,StartTime) <= @EndTime
)
, DateTimeCTE
as (
select StartDate, StartTime from DateCTE
cross join TimeCTE
)
SELECT CONVERT(DATETIME, CONVERT(CHAR(8), StartDate, 112)
+ ' ' + CONVERT(CHAR(8), StartTime, 108)) as 'datetime'
FROM DateTimeCTE
order by StartDate asc
,StartTime asc
;
我担心三个CTE以及查询中的其他所有内容都可能使其过于庞大。我是否对此感到担心,或者我只是偏执狂? :)
无论如何,如果有人知道更清洁的解决方案,我真的很想看到它。
再次感谢!
答案 0 :(得分:0)
你可以循环你的范围。例如,在SQL Server中,它将是
CREATE TABLE #Temp (result datetime)
WHILE @StartDate <= @EndDate
WHILE @StartTime <= @EndTime
INSERT INTO # Temp VALUES (@StartDate + @StartTime)
SET @StartTime = DATEADD (minute, @StartTime, @interval)
END
SET @StartDate = DATEADD (day, @StartDate, 1)
END
答案 1 :(得分:0)
考虑一个递归CTE,将两个项目转换为datetime,然后在时间部分(WHERE
)之间的CTE返回上运行07:00 - 07:30
。但是,您可能需要扩展默认的最大递归:
option (maxrecursion 500)
option (maxrecursion 0)
请参阅Rextester demo (由于其最大递归为100,使用间隔30)。
declare @StartDate date;
declare @EndDate date;
declare @StartTime time;
declare @EndTime time;
declare @interval int = 10;
set @StartDate = '2017-08-23';
set @EndDate = '2017-08-25';
set @StartTime = '07:00:00';
set @EndTime = '07:30:00';
WITH dates AS (
SELECT CAST(CAST(@StartDate AS VARCHAR(10)) + ' ' +
CAST(@StartTime AS VARCHAR(8)) AS DATETIME) AS START_TIME
UNION ALL
SELECT DATEADD(MINUTE, @interval, START_TIME)
FROM dates
WHERE START_TIME < CAST(CAST(@EndDate AS VARCHAR(10)) + ' ' +
CAST(@EndTime AS VARCHAR(8)) AS DATETIME)
)
SELECT START_TIME FROM dates
WHERE CONVERT(VARCHAR(8), START_TIME, 108) BETWEEN @StartTime AND @EndTime;