SQL:基于行值的动态联接
上下文: 我正在处理一些复杂的模式,并且有许多CTE和联接来达到这一点。这是一个淡化版本,完全不同的源数据和示例来说明我的观点(数据匿名性)。希望它能提供足够的快照 数据概述: 我有一项服务,可以生成30天的生产预测。为每个班次(上午/下午)的每个设施生成预测。生成的每个预测覆盖所有班次(上午/下午/晚上),因此它们共享一个通用的SQL:基于行值的动态联接,sql,amazon-redshift,Sql,Amazon Redshift,上下文: 我正在处理一些复杂的模式,并且有许多CTE和联接来达到这一点。这是一个淡化版本,完全不同的源数据和示例来说明我的观点(数据匿名性)。希望它能提供足够的快照 数据概述: 我有一项服务,可以生成30天的生产预测。为每个班次(上午/下午)的每个设施生成预测。生成的每个预测覆盖所有班次(上午/下午/晚上),因此它们共享一个通用的生成id,但不同的预测配置文件密钥 我想做的是:我想找到给定预测生成的预测误差总和,该误差受基于日期是工作日还是周末的动态日期范围的约束。总和必须仅在类似ID上分组 基
生成id
,但不同的预测配置文件密钥
我想做的是:我想找到给定预测生成的预测误差总和,该误差受基于日期是工作日还是周末的动态日期范围的约束。总和必须仅在类似ID上分组
基本上,temp表为每个工厂、每个日期、每个班次提供一条记录,并带有预测错误。我想根据日期是否为工作日/周末,对设施/班次/日期的历史错误进行动态求和,并且只对ID匹配的错误求和。。(希望有道理!!)
详细说明:我想查找按周部分分组“
,预测配置文件密钥“
,预测配置文件“
和预测生成id”分组的总和。我正在努力解决的问题是,我只想根据日期动态地总结错误:(a)如果日期是工作日,我想总结7天回顾期内最近5天的错误;或者(b)如果日期是周末,我想总结16天回顾期内最近3天的错误
理想情况下,为“总预测误差在回顾范围内”增加一列
具体示例:
- 对于
“设施a”
,“2020-11-22”
是一个周末。回溯范围为16天,因此“2020-11-21”和“2020-11-05”之间的任何日期都是合格的。最近的三个日期分别为“2020-11-21”、“2020-11-15”和“2020-11'14”。因此,误差之和为2000+3250+1050
- 对于
“设施a”
,“2020-11-20”
是一个工作日。回溯范围为7天,因此在“2020-11-19”和“2020-11-13”之间的任何日期。结果是“2020-11-19”:“2020-11-16”和“2020-11-13”
- 对于
'facility\u b'
,请注意“forecast\u generation\u id”中有一个更改。因此,“2020-11-20”的误差只有4565
我试过的:我承认我不太确定如何分解这部分。我确实考虑了一周的案子,但后来陷入了混乱。我考虑过使用秩窗口函数,但没有取得多大进展,因为我不确定如何实现动态回溯组件。然后,我还考虑做一些LISTAGG来获取所有日期,并进行REGEXP通配符查找,但这将非常缓慢
我正在寻找如何在SQL中实现这一点的指针。我不知道我的工具包中是否遗漏了一些东西,可以将其分解成我可以实现的东西
这实现了我想要做的。这里有两个学习点
自联接。我以前从未使用过,但现在可以看出它们为什么强大了李>
在WHERE子句中使用CASE语句
希望有一天这能帮助别人
select facility_name,
forecast_profile_key,
forecast_profile_id,
shift,
date_actuals,
week_part_grouping,
forecast_generation_id,
sum(forecast_error) forecast_err_calc
from (
select rank() over (partition by forecast_profile_id, forecast_profile_key, facility_name, a.date_actuals order by b.date_actuals desc) rnk,
a.facility_name, a.forecast_profile_key, a.forecast_profile_id, a.shift, a.date_actuals, a.week_part_grouping, a.forecast_generation_id, b.forecast_error
from seventh__error_calc a
join seventh__error_calc b
using (facility_name, forecast_profile_key, forecast_profile_id, week_part_grouping, forecast_generation_id)
where case when a.week_part_grouping = 'weekend' then b.date_actuals between a.date_actuals - 16 and a.date_actuals
when a.week_part_grouping = 'weekday' then b.date_actuals between a.date_actuals - 7 and a.date_actuals
end
) src
where case when week_part_grouping = 'weekend' then rnk < 4
when week_part_grouping = 'weekday' then rnk < 6
end
选择设施名称,
预测\u配置文件\u键,
预测配置文件id,
转移,
实际日期,
周(部分)分组,,
预测生成id,
总和(预测错误)预测错误计算
从(
在(按预测配置文件id、预测配置文件密钥、设施名称、a.date\U实际订单按b.date\U实际描述划分)rnk上选择rank(),
a、 设施名称、a.forecast\u profile\u关键字、a.forecast\u profile\u id、a.shift、a.date\u实际值、a.week\u part\u分组、a.forecast\u generation\u id、b.forecast\u错误
从第七次错误计算a
连接第七个错误计算b
使用(设施名称、预测配置文件密钥、预测配置文件id、每周部分分组、预测生成id)
其中,当a.week\u part\u grouping='weekend'时,b.date\u实际值介于a.date\u实际值-16和a.date\u实际值之间
当a.week_part_grouping='weekday'时,b.date_实际值介于a.date_实际值-7和a.date_实际值之间
结束
)src
其中,当week\u part\u分组为“weekend”时,则rnk<4
当week_part_分组='weekday'时,rnk<6
结束
SQL-这是用来生成表的吗?我们必须在上面应用动态连接吗?
select facility_name,
forecast_profile_key,
forecast_profile_id,
shift,
date_actuals,
week_part_grouping,
forecast_generation_id,
sum(forecast_error) forecast_err_calc
from (
select rank() over (partition by forecast_profile_id, forecast_profile_key, facility_name, a.date_actuals order by b.date_actuals desc) rnk,
a.facility_name, a.forecast_profile_key, a.forecast_profile_id, a.shift, a.date_actuals, a.week_part_grouping, a.forecast_generation_id, b.forecast_error
from seventh__error_calc a
join seventh__error_calc b
using (facility_name, forecast_profile_key, forecast_profile_id, week_part_grouping, forecast_generation_id)
where case when a.week_part_grouping = 'weekend' then b.date_actuals between a.date_actuals - 16 and a.date_actuals
when a.week_part_grouping = 'weekday' then b.date_actuals between a.date_actuals - 7 and a.date_actuals
end
) src
where case when week_part_grouping = 'weekend' then rnk < 4
when week_part_grouping = 'weekday' then rnk < 6
end