作为一些解决方案构建的一部分,我必须实现一个正在执行总计(累计总和计算)的视图。我采用了最简单,最基本的方法来将表与具有日期列表的表连接起来,但看来视图仍然相当慢。即使表本身只有约15K行,在表上添加索引也无济于事。我想知道是否有人可以建议哪种方法可以加快速度?
有几个注意事项:
我需要计算直到特定ProjectID
和ContractorID
为止的累积总和。因此对于同一日期,我可能会有很多ProjectID和ContractorId组合,但是Date,ProjectID和ContractorID的组合始终是唯一的
在主表中有日期,项目编号(但没有承包商编号),并且在此主日期表中我需要每个日期的累积总和,项目编号
我需要同时计算多个列的累计和,而不仅仅是一个
为了稍微介绍一下情况,我提供的表格是:
dbo.Project_Reporting_Schedule
,其中包含projectid,日期的主列表。对于每种组合,我都需要根据另一张表计算累计和。请注意,它没有承包商!
Project_value_delivery
是一个表,在该表中,我有一些实际值列用于执行累计和计算。它具有自己的日期集,该日期集可能与Project_Reporting_Schedule
中的日期匹配,也可能不匹配,因此我们不能仅将表本身联接起来。另请注意,它具有Contractorid!
当前,我有以下选择,这是不言自明的,只是将表与具有主日期列表的表中的值连接起来并进行求和。 Select的效果很好,但是即使只有15K记录,它也要花5秒钟才能运行,这相当慢。
select
pv2.ProjectID,
pv2.ContractorID,
pv1.Date,
sum(pv2.ValuePlanned) as PlannedCumulative,
sum(pv2.ValueActual) as ActualCumulative,
sum(pv2.MobilizationPlanned) as MobilizationPlanned,
sum(pv2.MobilizationActual) as MobilizationActual,
sum(pv2.EngineeringPlanned) as EngineeringPlanned,
sum(pv2.EngineeringActual) as EngineeringActual,
sum(pv2.ProcurementPlanned) as ProcurementPlanned,
sum(pv2.ProcurementActual) as ProcurementActual,
sum(pv2.ConstructionPlanned) as ConstructionPlanned,
sum(pv2.ConstructionActual) as ConstructionActual,
sum(pv2.CommisioningTestingPlanned) as CommisioningTestingPlanned,
sum(pv2.CommisioningTestingActual) as CommisioningTestingActual
from
dbo.Project_Reporting_Schedule as pv1
join
dbo.Project_value_delivery as pv2 on pv1.Date >= pv2.Date and pv1.ProjectID = pv2.ProjectID
group by
pv2.ProjectID, pv2.ContractorID, pv1.Date
更新
为进一步说明,我将执行计划放在这里: https://www.brentozar.com/pastetheplan/?id=H12t-O1PS
创建的索引是相同的,在两个表上我都具有Projectid,Date组合以及ProjectID和Date列上的独立索引。
在适用的情况下,所有索引都是唯一非聚集索引;在适用的情况下,所有索引都是非聚集索引。
我们可以看到它执行了“非聚集索引查找”,这花费了大部分执行时间。也许索引需要调整?
答案 0 :(得分:1)
好的,因此@Alex在注释窗口函数中的建议是一个可行的方法。与原始代码相比,下面的代码闪电般地运行:
select
pv2.ProjectID,
pv2.ContractorID,
pv1.Date,
sum(pv2.ValuePlanned) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as PlannedCumulative,
sum(pv2.ValueActual) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as ActualCumulative,
sum(pv2.MobilizationPlanned) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as MobilizationPlanned,
sum(pv2.MobilizationActual) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as MobilizationActual,
sum(pv2.EngineeringPlanned) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as EngineeringPlanned,
sum(pv2.EngineeringActual) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as EngineeringActual,
sum(pv2.ProcurementPlanned) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as ProcurementPlanned,
sum(pv2.ProcurementActual) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as ProcurementActual,
sum(pv2.ConstructionPlanned) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as ConstructionPlanned,
sum(pv2.ConstructionActual) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as ConstructionActual,
sum(pv2.CommisioningTestingPlanned) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as CommisioningTestingPlanned,
sum(pv2.CommisioningTestingActual) over (partition by pv2.ProjectID, pv2.ContractorID order by pv1.Date ROWS between unbounded preceding and current row) as CommisioningTestingActual
from
dbo.Project_Reporting_Schedule as pv1
join dbo.Project_value_delivery as pv2 on pv1.Date = pv2.Date and pv1.ProjectID = pv2.ProjectID
答案 1 :(得分:0)
将比较从JOIN
子句中取出,并将其移至WHERE
子句:
select
pv2.ProjectID,
pv2.ContractorID,
pv1.Date,
sum(pv2.ValuePlanned) as PlannedCumulative,
sum(pv2.ValueActual) as ActualCumulative,
sum(pv2.MobilizationPlanned) as MobilizationPlanned,
sum(pv2.MobilizationActual) as MobilizationActual,
sum(pv2.EngineeringPlanned) as EngineeringPlanned,
sum(pv2.EngineeringActual) as EngineeringActual,
sum(pv2.ProcurementPlanned) as ProcurementPlanned,
sum(pv2.ProcurementActual) as ProcurementActual,
sum(pv2.ConstructionPlanned) as ConstructionPlanned,
sum(pv2.ConstructionActual) as ConstructionActual,
sum(pv2.CommisioningTestingPlanned) as CommisioningTestingPlanned,
sum(pv2.CommisioningTestingActual) as CommisioningTestingActual
FROM
dbo.Project_Reporting_Schedule as pv1
join dbo.Project_value_delivery as pv2 on pv1.ProjectID = pv2.ProjectID
WHERE pv1.Date >= pv2.Date
GROUP BY pv2.ProjectID, pv2.ContractorID, pv1.Date