【发布时间】:2019-11-05 17:26:05
【问题描述】:
我从两个表(预测和订单)中提取数据来计算销售预测的准确性。
我正在采取的步骤:
确定产品-区域-需求月份的所有详尽组合 b/w 两个数据集...我们称之为 (1)
在预测数据中识别不同的预测快照...我们称之为 (2)
执行 (1) 和 (2) 的交叉连接...我们称之为 (3)
对订单和预测的 (3) 行执行等效的“SUMIF()”。例如,如果我将 2 月份的预测订单与实际订单进行比较,
1 月“INDPOR”预测---> 对于某些产品/地区-2 月交付组合:2 月预测(1 月生成)与 1 月 1 日之后预订且交付计划在 2 月的订单
2 月“INDPOR”预测--->对于相同的产品/地区-2 月交货日期组合:2 月预测(2 月生成)与 1 月 27 日*之后预订的订单* 2 月交货时间表
注 1:为同一月份生成多个预测
注 2:使用的会计日历定义;这就是为什么 2 月从 1 月 27 日开始
输出正确生成。但是,它非常缓慢(1小时+)。请帮助我对其进行微调并使其更快,因为我也需要将其用于更大的数据集。
其他细节:
- 我正在从我的桌面本地在 SQL Server 2014 上运行此程序。使用 SQL 数据导入向导将其从 Excel 文件中上传到 SQL 中
- 输入预测数据:ForecastAggTable
- 输入订单数据:OrderAggTable
代码:
Select *
from
(
Select *,
(Select isnull(sum([Forecast Qty]),0) from ForecastAggTable t2 where t2.LOB=D.LOB and
t2.[Demand Month]=D.[Demand Month] and t2.Class=D.Class
and t2.[Item Type]=D.[Item Type] and t2.[LoB Region]=D.[LoB Region] and
t2.[Key Account]=D.[Key Account] and t2.Country=D.Country
and t2.[Master Customer]=D.[Master Customer] and t2.[INDPOR Version]=D.[INDPOR Version])[Forecast Qty],
(
Select isnull(sum([Order Qty]),0) from OrderAggTable t1 where t1.LOB=D.LOB and
t1.[SAD Month]=D.[Demand Month] and t1.Class=D.Class
and t1.[Item Type]=D.[Item Type] and t1.[LoB Region]=D.[LoB Region] and
t1.[Key Account]=D.[Key Account] and t1.Country=D.Country
and t1.[Master Customer]=D.[Master Customer] and t1.[Book Date]>=D.[INDPOR Timestamp]
)[SAD-OrderQty],
(
Select isnull(sum([Order Revenue]),0) from OrderAggTable t1 where t1.LOB=D.LOB and
t1.[SAD Month]=D.[Demand Month] and t1.Class=D.Class
and t1.[Item Type]=D.[Item Type] and t1.[LoB Region]=D.[LoB Region] and
t1.[Key Account]=D.[Key Account] and t1.Country=D.Country
and t1.[Master Customer]=D.[Master Customer] and t1.[Book Date]>=D.[INDPOR Timestamp]
)[SAD-OrderRevenue],
(
Select isnull(sum([Order Qty]),0) from OrderAggTable t1 where t1.LOB=D.LOB and
t1.[RDD Month]=D.[Demand Month] and t1.Class=D.Class
and t1.[Item Type]=D.[Item Type] and t1.[LoB Region]=D.[LoB Region] and
t1.[Key Account]=D.[Key Account] and t1.Country=D.Country
and t1.[Master Customer]=D.[Master Customer] and t1.[Book Date]>=D.[INDPOR Timestamp]
)[RDD-OrderQty],
(
Select isnull(sum([Order Revenue]),0) from OrderAggTable t1 where t1.LOB=D.LOB and
t1.[RDD Month]=D.[Demand Month] and t1.Class=D.Class
and t1.[Item Type]=D.[Item Type] and t1.[LoB Region]=D.[LoB Region] and
t1.[Key Account]=D.[Key Account] and t1.Country=D.Country
and t1.[Master Customer]=D.[Master Customer] and t1.[Book Date]>=D.[INDPOR Timestamp]
)[RDD-OrderRevenue]
from
(
Select distinct LOB,[INDPOR Version],[INDPOR Timestamp],[Demand Month],
[Demand Quarter],[Min Date],Class,[Item Type],[Offer PF],
[LoB Region],[Key Account],Country,[Master Customer]
from
(
Select V.LOB,V.[SAD Month][Demand Month],V.[SAD Quarter][Demand Quarter],V.[SAD Min Date][Min Date],V.Class,
[Item Type],[Offer PF],[LoB Region],[Key Account],Country,[Master Customer]
from OrderAggTable V
union
(
Select Z.LOB,Z.[RDD Month][Demand Month],Z.[RDD Quarter][Demand Quarter],Z.[RDD Min Date][Min Date],Z.Class,
[Item Type],[Offer PF],[LoB Region],[Key Account],Country,[Master Customer]
from OrderAggTable Z
)
union
(
Select LOB,[Demand Month],[Demand Quarter],[Min Date],Class[Class],[Item Type],[Offer PF],[LoB Region],
[Key Account],Country,[Master Customer] from ForecastAggTable
)
)A
cross join
(
select distinct [INDPOR Version],[INDPOR Timestamp]
from ForecastAggTable
)B
)D
where [Min Date]>=[INDPOR Timestamp]
)E
where ([SAD-OrderQty] + [RDD-OrderQty] + [Forecast Qty]<>0)
【问题讨论】:
-
SSMS 查询分析器告诉你什么?
-
执行计划 通常是开始调查性能问题的好地方。请参阅paste the plan,了解在您的问题中包含执行计划的方法。
-
同意 cmets 关于查看执行计划以调试性能。此外,您在 select 子句中有 5 个子选择。每一个都将在结果集的每一行执行一次。因此,如果您有 1000 行,则子选择将执行 5 * 1000 次。这可能会导致性能问题。如果需要且可能,请尝试重写该结果并可能将中间结果存储在表 var 中。此外,联合的 select 语句没有 where 子句,请确保这是您想要的,因为您将提取完整的表。最后,&这是为了可维护性,将 select * 替换为列列表。
-
对每个表中的记录数有了一些了解,为我们提供了从哪里开始的线索。
distinct和union(与union all相比)也是昂贵的操作 - 确保这是您真正想要的。 -
实际查询运行大约需要 5 个小时。我根据前 100,000 名(选择前 100,000 名 *)得到的图表是否代表所需的努力?仍在运行完整的查询。
标签: sql sql-server database tsql