让我解释一下情况
我有两张桌子:
- 一个是存储设备故障,有自己的开始日期和结束日期。
- 其他用于存储休息时间,每个休息时间都有一个开始日期和结束日期。
例如,故障从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
我需要验证所有场景,如果故障首先开始并在休息时间结束等等......
我的问题是,存在一个自动执行此操作的函数吗?
还是更优雅的解决方案?
答案 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
如果我必须做你所说的话,这可能就是我的目标。
那就是说,在分析你的问题时,我想知道你是否不必为每个故障多次中断担心,如果你试图对结果集中的所有错误执行此操作,如果你正在聚合“每周每台设备的时间“或某事。如果是这样,你想要另一种方法。但这是另一个答案。