优化 Report 的 SQL 查询
Posted
技术标签:
【中文标题】优化 Report 的 SQL 查询【英文标题】:Optimize the SQL query for Report 【发布时间】:2019-05-07 09:49:15 【问题描述】:我必须为火车站的大门生成一个简单的正常运行时间报告。如果任何门有任何错误,则它在数据库中,具有特定原因以及中断的 startTime 和 EndTime。需要处理的场景很少:
-
如果一个车站有 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
【问题讨论】:
您是否还包括查询的执行计划 @ARr0w,请检查问题 @RamSingh 。 . .我建议你问一个新问题。专注于您引用的两个或三个表中的数据。显示您想要的结果——全部作为文本表格。清楚地解释逻辑并设置一个 db 小提琴。然后解释你有一个查询似乎需要很长时间。我可以阅读您的第一段,但我不知道解释与您的数据有何关系,因此我不会阅读第一段之外的内容。 请参阅paste the plan 了解在您的问题中包含执行计划的更好方法。 与其在几分钟内打破一个月并四处寻找,找到与该月重叠的所有中断行并处理它们以确定该月的总停机时间和任何重叠的停机时间会更有效。从您的表格中不清楚如何判断哪些读者被分配到给定的站点。重叠范围的一般检查是Start1 <= End2 and Start2 <= End1
。请参阅 overlap
标签 wiki 了解说明。
【参考方案1】:
您的日期生成器(使用递归)可能有点低效。 你可以试试这个:
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'
【讨论】:
以上是关于优化 Report 的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章