Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 计算实际停机时间,忽略日期/时间重叠_Sql_Sql Server_Sql Server 2008 R2 - Fatal编程技术网

Sql 计算实际停机时间,忽略日期/时间重叠

Sql 计算实际停机时间,忽略日期/时间重叠,sql,sql-server,sql-server-2008-r2,Sql,Sql Server,Sql Server 2008 R2,我正试图找出如何根据存储在表中的数据计算各种应用程序的实际停机时间 目前,我正在计算DowntimeStart和DowntimeEnd之间的差异,如DowntimeMinutes中所示 问题是,如果有一个交叉的时间,因为单独的组件是下降的,它应该计算总忽略了重叠 我期望的内容显示在“期望”列中 关于如何将查询组合在一起以实现这一点,您有什么想法吗 Application DowntimeStart DowntimeEnd Downti

我正试图找出如何根据存储在表中的数据计算各种应用程序的实际停机时间

目前,我正在计算DowntimeStart和DowntimeEnd之间的差异,如DowntimeMinutes中所示

问题是,如果有一个交叉的时间,因为单独的组件是下降的,它应该计算总忽略了重叠

我期望的内容显示在“期望”列中

关于如何将查询组合在一起以实现这一点,您有什么想法吗

Application         DowntimeStart           DowntimeEnd              DowntimeMinutes    Expected
Application Demo    2014-11-20 17:31:01.467 2014-11-20 18:01:01.243  30                 30
Application Demo    2014-11-28 17:59:00.987 2014-11-28 18:09:02.167  10                 26
Application Demo    2014-11-28 18:00:01.403 2014-11-28 18:25:01.443  25                 0
Application Demo    2014-11-29 19:13:08.580 2014-11-30 05:30:01.763  617                617
Application Demo    2014-11-30 01:55:01.953 2014-11-30 03:54:01.730  119                0
我已经查看并调查了这些选项,但它们没有实现上述目标:


使用新的测试用例更新

这里有一种技术可以计算出唯一的停机时间,然后将其与导致停机的初始停机时间对齐,以便实际值和预期值匹配

DECLARE @Downtime TABLE (
    ID INT PRIMARY KEY NOT NULL IDENTITY(1,1),
    Application VARCHAR(25), 
    DowntimeStart DATETIME,
    DowntimeEnd DATETIME,
    Expected INT
)

INSERT @Downtime (Application, DowntimeStart, DowntimeEnd, Expected) VALUES -- Act/Exp
    ('Application Demo', '2014-11-20 17:31:01.467', '2014-11-20 18:01:01.243', 30) -- 30/30
    ,('Application Demo', '2014-11-28 17:59:00.987', '2014-11-28 18:09:02.167', 26) -- 10/26
    ,('Application Demo', '2014-11-28 18:00:01.403', '2014-11-28 18:25:01.443', 0) -- 25/0
    ,('Application Demo', '2014-11-29 19:13:08.580', '2014-11-30 05:30:01.763', 617) -- 617/617
    ,('Application Demo', '2014-11-30 01:55:01.953', '2014-11-30 03:54:01.730', 0)
    ,('Application Demo 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397', 3514)
    ,('Application Demo 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397', 0)
    ,('Application Demo 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397', 0) 
    ,('Application Demo 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397', 0)
    ,('Application Demo 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397', 0) 

SELECT
    Downtimes.Application,
    Downtimes.DowntimeStart,
    Downtimes.DowntimeEnd,
    Downtimes.Expected,
    COALESCE(Actual, 0) AS Actual
FROM @Downtime Downtimes
    LEFT OUTER JOIN (
        SELECT DISTINCT
            D1.Application,
            MIN(CASE WHEN D1.DowntimeStart < D2.DowntimeStart THEN D1.ID ELSE D2.ID END) AS [ID],
            MIN(CASE WHEN D1.DowntimeStart < D2.DowntimeStart THEN D1.DowntimeStart ELSE D2.DowntimeStart END) AS [DowntimeStart],
            MAX(CASE WHEN D1.DowntimeEnd > D2.DowntimeEnd THEN D1.DowntimeEnd ELSE D2.DowntimeEnd END) AS [DowntimeEnd],
            DATEDIFF(MINUTE,
                MIN(CASE WHEN D1.DowntimeStart < D2.DowntimeStart THEN D1.DowntimeStart ELSE D2.DowntimeStart END),
                MAX(CASE WHEN D1.DowntimeEnd > D2.DowntimeEnd THEN D1.DowntimeEnd ELSE D2.DowntimeEnd END)) AS Actual
        FROM @Downtime D1
            INNER JOIN @Downtime D2
                ON D1.Application = D2.Application
                    AND (D1.DowntimeStart BETWEEN D2.DowntimeStart AND D2.DowntimeEnd
                        OR D2.DowntimeStart BETWEEN D1.DowntimeStart AND D1.DowntimeEnd)
        GROUP BY
            D1.Application,
            D1.DowntimeStart
    ) Outages
        ON Outages.ID = Downtimes.ID

我有一个类似的问题,我在我的问题中得到了答案

在您的例子中,这是通过使用top 1 self-outer apply来实现的,以获得重叠,然后使用重叠的开始时间,或者如果为空,则使用正常记录的结束时间作为结束时间

CREATE TABLE Downtime (
    Application VARCHAR(25), 
    DowntimeStart DATETIME,
    DowntimeEnd DATETIME,
    Expected INT
)

INSERT Downtime (Application, DowntimeStart, DowntimeEnd, Expected) VALUES -- Act/Exp
    ('Application Demo', '2014-11-20 17:31:01.467', '2014-11-20 18:01:01.243', 30) -- 30/30
    ,('Application Demo', '2014-11-28 17:59:00.987', '2014-11-28 18:09:02.167', 26) -- 10/26
    ,('Application Demo', '2014-11-28 18:00:01.403', '2014-11-28 18:25:01.443', 0) -- 25/0
    ,('Application Demo', '2014-11-29 19:13:08.580', '2014-11-30 05:30:01.763', 617) -- 617/617
    ,('Application Demo', '2014-11-30 01:55:01.953', '2014-11-30 03:54:01.730', 0)


SELECT
    Records.Application, Records.DowntimeStart, Records.DowntimeEnd, Records.Expected
  , DATEDIFF(minute, Records.DowntimeStart, COALESCE(Overlap.DowntimeStart, Records.DowntimeEnd)) AS Actual
--  , Overlap.Application, Overlap.DowntimeStart, Overlap.DowntimeEnd -- For Verification Purposes
FROM Downtime Records
  OUTER APPLY (
    SELECT TOP 1 Overlap.Application, Overlap.DowntimeStart, Overlap.DowntimeEnd
    FROM Downtime Overlap
    WHERE Records.Application = Overlap.Application
      AND Overlap.DowntimeStart > Records.DowntimeStart
      AND Overlap.DowntimeStart BETWEEN Records.DowntimeStart AND Records.DowntimeEnd
    ORDER BY Overlap.DowntimeStart
    ) Overlap

这是解决方案。

这里的小数据验证问题:最后一行的开始时间在前一行的开始和结束时间之间,因此应该影响两个持续时间。非常感谢杰森,在测试所有数据之前,我没有考虑过这个问题。如果您有以下内容,请参阅下一条消息,它将为所有返回相同的值。是否要修改查询以将其考虑在内?插入#表名(应用程序、DowntimeStart、DowntimeEnd、预期)值-(“应用程序演示2”、“2014-12-19 23:09:01.303”、“2014-12-22 09:43:01.397”、3514),(“应用程序演示2”、“2014-12-19 23:09:01.303”、“2014-12-22 09:43:01.397”、0),(“应用程序演示2”,“2014-12-19 23:09:01.303”,“2014-12-22 09:43:01.397”,0),(“应用程序演示2”,“2014-12-19 23:09:01.303”,“2014-12-22 09:43:01.397”,0)-,(“应用程序演示2”,“2014-12-19 23:09:01.303”,“2014-12-22 09:43:01.397”,0)您的表是否有可用于更改的主键?是的,它有。直接命名为“ID”INT.的类型非常感谢Jaaz,在我测试了所有数据之前,有一个问题我没有考虑。如果你有下面的消息,请看下一条消息,它会为所有的人返回相同的值。无论如何,修改查询以考虑这一点。(“应用程序演示2”,“2014-12-19 23:09:01.303”,“2014-12-22 09:43:01.397',3514),(“应用程序演示2”,“2014-12-19 23:09:01.303”,“2014-12-22 09:43:01.397',0),(“应用程序演示2”,“2014-12-19 23:09:01.303”,“2014-12-22 09:43:01.397',0),(“应用程序演示2”,“2014-12-19 23:09:01.303”,“2014-12-22 09:01.397',0)-,”,(“应用程序演示2”,“2014-12-19 23:09:01.303”,“2014-12-22 09:43:01.397”,0)
CREATE TABLE Downtime (
    Application VARCHAR(25), 
    DowntimeStart DATETIME,
    DowntimeEnd DATETIME,
    Expected INT
)

INSERT Downtime (Application, DowntimeStart, DowntimeEnd, Expected) VALUES -- Act/Exp
    ('Application Demo', '2014-11-20 17:31:01.467', '2014-11-20 18:01:01.243', 30) -- 30/30
    ,('Application Demo', '2014-11-28 17:59:00.987', '2014-11-28 18:09:02.167', 26) -- 10/26
    ,('Application Demo', '2014-11-28 18:00:01.403', '2014-11-28 18:25:01.443', 0) -- 25/0
    ,('Application Demo', '2014-11-29 19:13:08.580', '2014-11-30 05:30:01.763', 617) -- 617/617
    ,('Application Demo', '2014-11-30 01:55:01.953', '2014-11-30 03:54:01.730', 0)


SELECT
    Records.Application, Records.DowntimeStart, Records.DowntimeEnd, Records.Expected
  , DATEDIFF(minute, Records.DowntimeStart, COALESCE(Overlap.DowntimeStart, Records.DowntimeEnd)) AS Actual
--  , Overlap.Application, Overlap.DowntimeStart, Overlap.DowntimeEnd -- For Verification Purposes
FROM Downtime Records
  OUTER APPLY (
    SELECT TOP 1 Overlap.Application, Overlap.DowntimeStart, Overlap.DowntimeEnd
    FROM Downtime Overlap
    WHERE Records.Application = Overlap.Application
      AND Overlap.DowntimeStart > Records.DowntimeStart
      AND Overlap.DowntimeStart BETWEEN Records.DowntimeStart AND Records.DowntimeEnd
    ORDER BY Overlap.DowntimeStart
    ) Overlap