随着时间流逝的操作

时间:2010-11-23 21:59:02

标签: sql-server

让我解释一下情况

我有两张桌子:

- 一个是存储设备故障,有自己的开始日期和结束日期。

- 其他用于存储休息时间,每个休息时间都有一个开始日期和结束日期。

例如,故障从9:10开始,到9:16结束。休息时间从9:14开始,到9点18分结束,故障时间为4分钟。故障的2分钟不计算因为休息时间。我需要获取“2分钟”值才能将其包含在报告中

要计算它,我使用标量值函数:

DECLARE @Time int;

SET @Time = 0;

IF (@BreakStartDate > @FaultStartDate) AND (@BreakEndDate < @FaultEndDate)
    SET @Time = DATEDIFF(SECOND, @BreakStartDate, @BreakEndDate);

ELSE IF (@FaultStartDate > @BreakStartDate) AND (@FaultEndDate < @BreakEndDate)
    SET @Time = DATEDIFF(SECOND, @FaultStartDate, @FaultEndDate);

ELSE IF (@FaultStartDate < @BreakStartDate) AND ((@FaultEndDate > @BreakStartDate) AND (@FaultEndDate < @BreakEndDate))
    SET @Time = DATEDIFF(SECOND, @BreakStartDate, @FaultEndDate);

ELSE IF (@FaultEndDate > @BreakEndDate) AND ((@FaultStartDate > @BreakStartDate) AND (@FaultStartDate < @BreakEndDate))
    SET @Time = DATEDIFF(SECOND, @FaultStartDate, @BreakEndDate);

RETURN @Time

我需要验证所有场景,如果故障首先开始并在休息时间结束等等......

我的问题是,存在一个自动执行此操作的函数吗?

还是更优雅的解决方案?

2 个答案:

答案 0 :(得分:0)

AFAIK没有内置功能。但是,如果您将所有日期转换为自某个随机开始日期以来的秒数,我认为您可以计算出错误的时间(以伪代码形式):

max(0; b1 - f1) - max(0; b2 - f2)

其中b1,f1,b2和f2在下面的代码中给出,我已经把SQL用来计算上面的表达式(未经测试):

 DECLARE @startDate DATETIME
 SET @startDate = '2010-01-01' -- Some date that must be smaller than all fault dates and break dates

 DECLARE @breakStartDate DATETIME
 DECLARE @breakEndDate DATETIME
 DECLARE @faultStartDate DATETIME
 DECLARE @faultEndDate DATETIME

 DECLARE @b1 INT
 DECLARE @b2 INT
 DECLARE @f1 INT
 DECLARE @f2 INT

 -- Set values for break and fault dates here
 SET @breakStartDate = ....
 SET @breakEndDate = ....
 SET @faultStartDate = ....
 SET @faultEndDate = ....

 SET @b1 = DATEDIFF(SECOND, @startDate, @breakStartDate)
 SET @b2 = DATEDIFF(SECOND, @startDate, @breakEndDate)
 SET @f1 = DATEDIFF(SECOND, @startDate, @faultStartDate)
 SET @f2 = DATEDIFF(SECOND, @startDate, @faultEndDate)

 DECLARE @time INT

 SET @time = 
 CASE 
  WHEN @b1 - @f1 < 0 THEN 0
  ELSE @b1 - @f1
 END 
 +
 CASE
  WHEN @b2 - @f2 < 0 THEN 0
  ELSE @b2 - @f2
 END 

 SELECT @time

我认为它更优雅,更不容易出错,但这是一个品味问题。它可能更难阅读。

答案 1 :(得分:0)

我正在使用时间输入工具执行类似操作,并且需要检测输入时间之间的重叠。如果您真正需要的是“我有一个错误。在故障期间会有1个休息时间。给我他们共同事件的时间”,然后你的功能就在正确的轨道上。

当我做我的时,我发现在视觉上探索测试用例比真值表更好,并且两者都比散文或代码更好。

Case 1:                            Case 2:
Fault:  |-------|                  Fault:  |----------|
Break:              |-------|      Break:        |----------|

Case 3:                            Case 4:
Fault:       |----------|          Fault:  |----------|
Break:  |----------|               Break:    |------|

...等

至于优雅地做到这一点,我会指出如果两次失误之间有任何重叠,那么始终最终需要更大的开始日期。像这样:

Start Dates:
Fault:    |----     ...  |----  ...     |----
Break:       |----  ...  |----  ...  |----
Verdict:    break        either        fault

...和最小的结束日期类似。因为我们感兴趣的区域是两者都已经开始并且都没有完成。所以你的逻辑可以变成:

DECLARE @Time int, @biggestStart datetime, @smallestEnd datetime;
SET @Time = 0;

IF (@BreakStartDate < @FaultEndDate) AND (@BreakEndDate > @FaultStartDate)
BEGIN
    -- We have overlap.
    -- Poor man's Math.Max and Math.Min:
    SET @biggestStart = CASE WHEN @FaultStartDate > @BreakStartDate THEN @FaultStartDate ELSE @BreakEndDate END;
    SET @smallestEnd = CASE WHEN @FaultEndDate < @BreakEndDate THEN @FaultEndDate ELSE @BreakEndDate END;

    SET @Time = DATEDIFF(SECOND, @biggestStart, @smallestEnd);
END
RETURN @Time

如果我必须做你所说的话,这可能就是我的目标。

那就是说,在分析你的问题时,我想知道你是否不必为每个故障多次中断担心,如果你试图对结果集中的所有错误执行此操作,如果你正在聚合“每周每台设备的时间“或某事。如果是这样,你想要另一种方法。但这是另一个答案。

相关问题