将日期范围和时间范围组合到一组结果中,这些结果包含日期范围SQL中包含的每一天的时间范围

时间:2017-09-15 13:19:54

标签: sql sql-server date datetime common-table-expression

如果我有一个开始和结束日期,然后是一个单独的开始和结束时间,我想返回日期范围内每个日期的时间范围。

这是一个小例子: 我将以下变量设置为以下示例值:

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以及查询中的其他所有内容都可能使其过于庞大。我是否对此感到担心,或者我只是偏执狂? :)

无论如何,如果有人知道更清洁的解决方案,我真的很想看到它。

再次感谢!

2 个答案:

答案 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;