Sql ,但是我需要在多个站点的多个系统上运行相同的代码(大约总共60个),所以我认为它会变得非常慢。粒度很重要(某些故障对于系统重置而言不到一分钟),因此也必须使用较短的时间间隔,这会使情况变得更糟。谢谢你的回答,我真的很感激!诚然,此解决方案可能无法很好地扩展
Sql ,但是我需要在多个站点的多个系统上运行相同的代码(大约总共60个),所以我认为它会变得非常慢。粒度很重要(某些故障对于系统重置而言不到一分钟),因此也必须使用较短的时间间隔,这会使情况变得更糟。谢谢你的回答,我真的很感激!诚然,此解决方案可能无法很好地扩展,sql,datetime,overlapping,Sql,Datetime,Overlapping,,但是我需要在多个站点的多个系统上运行相同的代码(大约总共60个),所以我认为它会变得非常慢。粒度很重要(某些故障对于系统重置而言不到一分钟),因此也必须使用较短的时间间隔,这会使情况变得更糟。谢谢你的回答,我真的很感激!诚然,此解决方案可能无法很好地扩展,尤其是在较长的时间内。我还想说,CTE方法可能也会受到缩放问题的影响,但会受到事件数量的影响,而不一定是时间范围的影响。我会测试两者是否诚实,并留意另一种方法——哪一种更适合你的需要。 Outage_ID StartDateTime
,但是我需要在多个站点的多个系统上运行相同的代码(大约总共60个),所以我认为它会变得非常慢。粒度很重要(某些故障对于系统重置而言不到一分钟),因此也必须使用较短的时间间隔,这会使情况变得更糟。谢谢你的回答,我真的很感激!诚然,此解决方案可能无法很好地扩展,尤其是在较长的时间内。我还想说,CTE方法可能也会受到缩放问题的影响,但会受到事件数量的影响,而不一定是时间范围的影响。我会测试两者是否诚实,并留意另一种方法——哪一种更适合你的需要。
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 |---|
--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
DECLARE @Faults TABLE (
StartDateTime DATETIME NOT NULL,
EndDateTime DATETIME NULL
)
INSERT INTO @Faults (StartDateTime, EndDateTime)
SELECT '2013-07-03 08:30', '2013-07-04 10:00'
UNION ALL SELECT '2013-07-04 12:00', NULL
UNION ALL SELECT '2013-07-04 12:30', '2013-07-04 12:35'
-- "Unpivot" the events and assign 1 to a start and -1 to an end
;WITH FaultEvents AS (
SELECT *, Ord = ROW_NUMBER() OVER(ORDER BY EventDateTime)
FROM (
SELECT EventDateTime = StartDateTime, Evt = 1
FROM @Faults
UNION ALL SELECT EndDateTime, Evt = -1
FROM @Faults
WHERE EndDateTime IS NOT NULL
) X
)
-- Running total of Evt gives the current state at each date/time point
, FaultEventStates AS (
SELECT A.Ord, A.EventDateTime, A.Evt, [State] = (SELECT SUM(B.Evt) FROM FaultEvents B WHERE B.Ord <= A.Ord)
FROM FaultEvents A
)
SELECT StartDateTime = S.EventDateTime, EndDateTime = F.EventDateTime
FROM FaultEventStates S
OUTER APPLY (
-- Find the nearest transition to the no-fault state
SELECT TOP 1 *
FROM FaultEventStates B
WHERE B.[State] = 0
AND B.Ord > S.Ord
ORDER BY B.Ord
) F
-- Restrict to start events transitioning from the no-fault state
WHERE S.Evt = 1 AND S.[State] = 1