SQL查找重叠的时间段和子故障

Ric*_*rry 9 sql datetime overlapping

长时间跟踪者,第一次海报(和SQL初学者).我的问题类似于这一个SQL来查找从多个重叠间隔过去的时间,除了我能够使用CTE,UDF等,我正在寻找更多的细节.

在一台大型设备上,我记录了所有出现的故障.系统的不同子组件可能出现故障,有些可能完全脱机(完全停机=是),而其他子组件则没有(完全停机=否).故障可能会在时间上重叠,如果故障尚未修复,则可能没有结束时间.

Outage_ID     StartDateTime     EndDateTime     CompleteOutage
1             07:00 3-Jul-13    08:55 3-Jul13   Yes
2             08:30 3-Jul-13    10:00 4-Jul13   No
3             12:00 4-Jul-13                    No
4             12:30 4-Jul13     12:35 4-Jul-13  No


1 |---------|
2    |---------|
3                 |--------------------------------------------------------------
4                      |---|
Run Code Online (Sandbox Code Playgroud)

我需要能够在用户定义的时间段内完成工作,整个系统完全正常运行多长时间(无故障),退化多长时间(一个或多个非完全中断)以及无法运行多长时间(一个或多个完整系统)停电).我还需要能够在任何给定的时间段内解决系统中出现的故障.我想在打开或关闭故障的任何时候创建一个"阶段变化"表,但我仍然坚持最好的方法 - 对这个或更好的解决方案的任何帮助将不胜感激!

use*_*839 1

以下是实现此功能的粗略指南。它将与日期间隔表和 15 分钟间隔表进行比较。然后,它将对中断事件进行求和(每个时间间隔 1 个事件),但如果存在完全中断,则不会对部分中断求和。

如果需要,您可以使用更细粒度的时间间隔,我选择 15 分钟以提高编码速度。

我已经设置了一个日期间隔表“CAL.t_Calendar”,因此您需要创建一个自己的日期间隔表来运行此代码。

请注意,这并不代表您应该使用的实际代码。它只是为了演示并为您指明可能的方向......

编辑我刚刚意识到我没有考虑到空结束日期。该代码需要修改以检查 NULL endDates 并使用 @EndDate 或 GETDATE()(如果 @EndDate 是将来的时间)

            --drop table ##Events
            CREATE TABLE #Events (OUTAGE_ID INT IDENTITY(1,1) PRIMARY KEY 
                                    ,StartDateTime datetime
                                    ,EndDateTime datetime
                                    , completeOutage bit)

            INSERT INTO #Events VALUES ('2013-07-03 07:00','2013-07-03 08:55',1),('2013-07-03 08:30','2013-07-04 10:00',0)
                                        ,('2013-07-04 12:00',NULL,0),('2013-07-04 12:30','2013-07-04 12:35',0)


            --drop table #FiveMins
            CREATE TABLE #FiveMins (ID int IDENTITY(1,1) PRIMARY KEY, TimeInterval Time)


            DECLARE @Time INT = 0

            WHILE @Time <= 1410 --number of 15 min intervals in day * 15 

            BEGIN

                INSERT INTO #FiveMins SELECT DATEADD(MINUTE , @Time,  '00:00')

                SET @Time = @Time + 15

            END

            SELECT * from #FiveMins



            DECLARE @StartDate DATETIME = '2013-07-03'
            DECLARE @EndDate DATETIME = '2013-07-04 23:59:59.999'


            SELECT SUM(FullOutage) * 15 as MinutesFullOutage
                    ,SUM(PartialOutage) * 15 as MinutesPartialOutage
                    ,SUM(NoOutage) * 15  as MinutesNoOutage
            FROM
            (
                SELECT DateAnc.EventDateTime
                        , CASE WHEN COUNT(OU.OUTAGE_ID) > 0 THEN 1 ELSE 0 END AS FullOutage
                        , CASE WHEN COUNT(OU.OUTAGE_ID) = 0 AND COUNT(pOU.OUTAGE_ID) > 0 THEN 1 ELSE 0 END AS PartialOutage
                        , CASE WHEN COUNT(OU.OUTAGE_ID) > 0 OR  COUNT(pOU.OUTAGE_ID) > 0 THEN 0 ELSE 1 END AS NoOutage
                FROM 
                (
                    SELECT CAL.calDate + MI.TimeInterval AS EventDateTime
                    FROM CAL.t_Calendar CAL

                    CROSS JOIN #FiveMins MI

                    WHERE CAL.calDate BETWEEN @StartDate AND @EndDate 
                ) DateAnc

                LEFT JOIN #Events OU
                ON DateAnc.EventDateTime BETWEEN OU.StartDateTime AND OU.EndDateTime
                AND OU.completeOutage = 1

                LEFT JOIN #Events pOU
                ON DateAnc.EventDateTime BETWEEN pOU.StartDateTime AND pOU.EndDateTime
                AND pOU.completeOutage = 0

                GROUP BY DateAnc.EventDateTime
            ) AllOutages
Run Code Online (Sandbox Code Playgroud)