SQL计算时间范围

时间:2016-11-09 09:35:24

标签: sql sql-server date stored-procedures

我有一张包含不同时间范围的表格:

Id  Start Time  End Time    Points
1   0:00        3:00        10
2   3:01        6:00        20
3   6:01        23:59       30

现在我需要根据指定的时间计算两个日期范围之间达到的分数。

Start date = 11/9/2016 18:17:00 and 
End date = 11/10/2016 01:20:00

我需要计算这两个日期之间获得的点数之和。 开始日期是18:17的时间属于Id 3,其点为30.因此计算将是,

18:17 to 23:59 -> 6 hrs -> 6 * 30 = 180 points

结束时间01:20属于Id 1

0:00 to 1:20 -> 2 hrs 
(if minute is greater than zero, it is rounded to next hour, ie; 2) -> 2 * 10 = 20 points

所以获得的总分将是200分。 如果开始和结束日期的差异大于一天,那么考虑时差,对我没有帮助。

表格结构: Id - int, 开始时间 - 时间(7), 结束时间 - 时间(7), Points - int

如何使用SQL为此编写查询?

1 个答案:

答案 0 :(得分:1)

这个问题很好。

您可以如下所示:

DECLARE @Tbl TABLE (Id INT, StartTime TIME, EndTime TIME, Points INT)
INSERT INTO @Tbl
VALUES                 
(1,   '0:00',     '3:00' ,       10),
(2,   '3:01',     '6:00' ,       20),
(3,   '6:01',     '23:59',       30)


DECLARE @StartDate DATETIME = '2016.11.09 18:17:00'
DECLARE @EndDate DATETIME = '2016.11.10 01:20:00'


;WITH CTE
AS
(
    SELECT 1 AS RowId, @StartDate CurrentDate, 0 Point, @StartDate DateVal UNION ALL
    SELECT
        A.RowId ,
        IIF((A.CurrentDate + A.EndTime) > @EndDate, @EndDate, DATEADD(MINUTE, 1, (A.CurrentDate + A.EndTime))) AS CurrentDate,
        A.Points,
        IIF((A.CurrentDate + A.EndTime) > @EndDate, @EndDate, (A.CurrentDate + A.EndTime)) DateVal
    FROM
    (
        SELECT 
            C.RowId + 1 AS RowId,  
            CAST(CAST(CurrentDate AS DATE) AS DATETIME) CurrentDate,
            CAST((SELECT T.EndTime FROM @Tbl T WHERE CAST(CurrentDate AS TIME) BETWEEN T.StartTime AND T.EndTime) AS DATETIME) AS EndTime,
                (SELECT T.Points FROM @Tbl T WHERE CAST(CurrentDate AS TIME) BETWEEN T.StartTime AND T.EndTime) AS Points,
            C.CurrentDate AS TempDate
         FROM CTE C         
    ) A
    WHERE           
        A.TempDate <> IIF((A.CurrentDate + A.EndTime) > @EndDate, @EndDate, DATEADD(MINUTE, 1, (A.CurrentDate + A.EndTime)))
), CTE2
AS
(
    SELECT
        C.RowId ,
        C.CurrentDate ,
        C.Point ,
        C.DateVal,
        DATEDIFF(MINUTE, LAG(C.DateVal) OVER (ORDER BY C.RowId), C.DateVal) MinuteOfDateDiff
    FROM
        CTE C
)


 SELECT 
    SUM(CEILING(C.MinuteOfDateDiff * 1.0 / 60.0) * C.Point)
 FROM 
    CTE2 C

结果:200