优化报表的SQL查询

时间:2019-05-07 09:49:16

标签: sql sql-server tsql query-optimization

我必须为火车站的登机口生成一个简单的正常运行时间报告。如果任何门有任何错误,则该错误在数据库中具有特定原因,并且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 :(得分:0)

“日期”构建器(使用递归)可能效率低下。 您可以尝试以下方法:

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'