2017-09-15 128 views
1

如果我有开始和结束日期,然后是单独的开始和结束时间,喜欢返回日期范围内每个日期的时间范围。将日期范围和时间范围组合到一组结果中,该结果包含日期范围中包含的每一天的时间范围SQL

这里有一个小例子: 我有以下变量设置为以下样本值:

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 
; 

我担心在查询一切沿着三个热膨胀系数可能使其体积太大。我是否有权为此担忧,还是我只是偏执狂? :)

在任何情况下,如果有人确实知道更清洁的解决方案,我会非常有兴趣看到它。

再次感谢!

+1

这是工作代码,应该发布在CodeReview上,而不是SO上。 –

+0

标记您正在使用的dbms。该代码是特定于产品的。 – jarlh

+2

这个问题属于codereview.stackexchange.com – scsimon

回答

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 
0

铸造这两个项目为日期时间,然后运行在一个CTE的WHERE时间部分(07:00 - 07:30)之间返回考虑一个递归CTE。但是,您可能需要扩大默认的最大递归:

  • 与定义的数字:option (maxrecursion 500)
  • 无限递归:option (maxrecursion 0)

Rextester演示(使用30由于间隔到它们的最大递归100)

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;