我有一张每月生产值的表格。
示例:
Outdate | Prod Value | ID
2/28/19 | 110 | 4180
3/31/19 | 100 | 4180
4/30/19 | 90 | 4180
我还有一个表,其中包含每月的预测值。
示例:
Forecast End Date | Forecast Value | ID
2/28/19 | 120 | 4180
3/31/19 | 105 | 4180
4/30/19 | 80 | 4180
我想创建一个表,该表的行包含ID,产品值,当前月份(例如3月)预测,上个月预测,下个月预测。
我想要什么:
ID | Prod Value | Outdate | Current Forecast | Previous Forecast | Next Forecast
4180 | 100 | 3/31/19 | 105 | 120 | 80
问题在于,当我使用DATEADD
从上个月的“预测”表中引入特定值时,最终值中缺少了随机月份。
在下个月和上个月的预测中添加时,我尝试在DateDimension表中添加另一个LEFT JOIN
/ INNER JOIN
,但这不能解决问题或添加太多行
我的DateDimension表具有以下列:DateKey 日期,日期,DaySuffix,工作日,WeekDayName,IsWeekend,IsHoliday,DOWInMonth,DayOfYear,WeekOfMonth,WeekOfYear,ISOWeekOfYear,Month,MonthName,Quarter,QuarterName,Year,MMYYYY,MonthYear,FirstDayOfMonth,LastDayOfMonth,FirstDayOfearter,FirstDayOfearter, FirstDayOfNextMonth,FirstDayOfNextYear
我的查询就是这样(为简单起见缩写)
SELECT A.ArchiveKey, BH.ID, d.[Date], BH.Outdate, BH.ProdValue, BH.Forecast, BHP.Forecast, BHN.Foreceast
FROM dbo.BudgetHistory bh
INNER JOIN dbo.DateDimension d ON bh.outdate = d.lastdayofmonth
INNER JOIN dbo.Archive a ON bh.ArchiveKey = a.ArchiveKey
LEFT JOIN dbo.BudgetHistory bhp ON bh.ID = bhp.ID AND bhp.outdate = DATEADD(m, - 1, bh.Outdate)
LEFT JOIN dbo.BudgetHistory bhn ON bh.ID = bhn.ID AND bhn.outdate = DATEADD(m, 1, bh.Outdate)
WHERE bh.ID IS NOT NULL
我得到这样的东西:
+------+------------+---------+------------------+-------------------+---------------+
| ID | Prod Value | Outdate | Current Forecast | Previous Forecast | Next Forecast |
+------+------------+---------+------------------+-------------------+---------------+
| 4180 | 110 | 2/28/19 | 120 | NULL | NULL |
| 4180 | 100 | 3/31/19 | 105 | 120 | 80 |
| 4180 | 90 | 4/30/19 | 80 | NULL | NULL |
+------+------------+---------+------------------+-------------------+---------------+
该模式似乎没有遵循任何合理的原则。 我希望为每一行填写值。
答案 0 :(得分:2)
您可以联接表,然后使用窗口函数LEAD()
和LAG()
恢复下一个和上一个预测值:
SELECT
p.ID,
p.ProdValue,
p.Outdate,
f.ForecastValue,
LAG(f.ForecastValue) OVER(PARTITION BY f.ID ORDER BY f.ForecastEndDate) PreviousForecast,
LEAD(f.ForecastValue) OVER(PARTITION BY f.ID ORDER BY f.ForecastEndDate) NextForecast
FROM prod p
INNER JOIN forecast f ON p.ID = f.ID AND p.Outdate = f.ForecastEndDate
此 demo on DB Fiddle 及其示例数据将返回:
ID | ProdValue | Outdate | ForecastValue | PreviousForecast | NextForecast ---: | --------: | :------------------ | ------------: | ---------------: | -----------: 4180 | 110 | 28/02/2019 00:00:00 | 120 | null | 105 4180 | 100 | 31/03/2019 00:00:00 | 105 | 120 | 80 4180 | 90 | 30/04/2019 00:00:00 | 80 | 105 | null
答案 1 :(得分:0)
DATEADD
仅在新计算的值不是有效日期时才进行月末调整。因此DATEADD(month,-1,'20190331')
产生2月28日。但是DATEADD(month,-1,'20190228')
的产生时间是1月28日,而不是31日。
我可能会选择GMB's answer。如果您想基于DATEADD
进行操作,则可以使用:
bhp.outdate = DATEADD(month, DATEDIFF(month,'20010131', bh.Outdate) ,'20001231')
这总是从bh.OutDate
开始计算上个月的最后一天,但是它是通过将其计算为固定日期的偏移量,然后将该偏移量应用于不同的固定日期。
您可以颠倒20010131
和20001231
的位置来计算下个月而不是前一个月。除了他们都拥有31天并希望应用“一个月”的关系外,对他们没有任何意义。