Оптимизировать SQL-запрос для отчета - PullRequest
0 голосов
/ 07 мая 2019

Я должен создать простой отчет о времени работы ворот на железнодорожных станциях.если есть какая-либо ошибка для какого-либо шлюза, она находится в БД с определенной причиной, а также startTime и EndTime сбоя.У вас есть несколько сценариев, о которых нужно позаботиться:

  1. Если на одной станции 2 шлюза, один работает в течение первых 15 дней месяца, а второй - в течение следующих 15 дней, поэтому в целом одинобоих ворот работают.Поэтому значение для этой станции должно быть 100%.Если оба входа и вниз в течение любого количества дней, это не будет в этом проценте.

Я записал запрос, но на выполнение нескольких сотен тысяч записей уходит 5-6 минут. Так что это душит систему.

declare @dt_start datetime, @dt_end datetime
set @dt_start = '2019-04-01 00:00';
set @dt_end = '2019-04-30 23:59';
DROP TABLE IF EXISTS #minutesTime;
with cte_Dates as (
        SELECT @dt_start as uptimeMinute
        UNION ALL
        SELECT DATEADD(MINUTE,1,uptimeMinute)
        FROM cte_Dates
        WHERE DATEADD(MINUTE,1,uptimeMinute) < @dt_end
    )

SELECT * 
INTO #minutesTime FROM cte_Dates
WHERE CAST(uptimeMinute as time) >= '05:00:00'
or CAST(uptimeMinute as time) < '02:00:00'
OPTION(MAXRECURSION 0);

SELECT
uptimeMinute,
count(DISTINCT o.ReaderID) as numOfflineReaders
FROM #minutesTime m
CROSS JOIN Readers r 
JOIN Outages o
ON r.ReaderId = o.ReaderId
WHERE 
uptimeMinute BETWEEN o.OutageStart AND o.OutageEnd
GROUP BY 
uptimeMinute having count(DISTINCT o.ReaderID)=3
ORDER BY 
uptimeMinute;

Таблица определений:

Считыватели:

ReaderId NotificationsDisabled
1        0
2        1

Отключения:

OutageId    SourceType  SourceId    OutageStart                     OutageEnd                       OutageSeconds   ReaderId
1           Faults          1       2019-03-28 10:13:35.6700000     2019-03-31 00:21:45.5900000     223690          24      

Execution Plan for last query

1 Ответ

0 голосов
/ 07 мая 2019

Ваш построитель дат (с использованием рекурсии), вероятно, немного неэффективен.Вы можете попробовать это:

DECLARE @StartDate DATETIME = '2019-04-01 00:00'  , @EndDate DATETIME= '2019-04-30 23:59';



WITH dates as (
SELECT  DATEADD(MINUTE, nbr - 1, @StartDate) as uptimeMinute
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY c.object_id , c.a ) AS Nbr
          FROM      
          (SELECT c.object_id, 1 as a FROM sys.columns c
          UNION ALL 
          SELECT c.object_id, 0 as a FROM sys.columns c) c
        ) nbrs
WHERE   nbr - 1 <= DATEDIFF(MINUTE, @StartDate, @EndDate)
)
SELECT uptimeMinute into #minute
from dates
WHERE CAST(uptimeMinute as time) >= '05:00:00'
or CAST(uptimeMinute as time) < '02:00:00'
...