2016-11-23 46 views
2

我有一个表格,称为预测,我们将在未来6个月内存储所有产品的预测。例如,当我们在11月份时,我们创建了12月,1月,2月,3月,4月和5月的预测。该预测表看起来像下面通过postgres计算过去3个月中的月度预测

+----------------+---------------+--------------+----------+ 
| product_number | forecasted_on | forecast_for | quantity | 
+----------------+---------------+--------------+----------+ 
| Prod 1   | 2016-11-01 | 2016-12-01 |  100 | 
| Prod 1   | 2016-11-01 | 2017-01-01 |  200 | 
| Prod 1   | 2016-11-01 | 2017-02-01 |  300 | 
| Prod 1   | 2016-11-01 | 2017-03-01 |  400 | 
| Prod 1   | 2016-11-01 | 2017-04-01 |  500 | 
| Prod 1   | 2016-11-01 | 2017-05-01 |  600 | 
+----------------+---------------+--------------+----------+ 

一个在表格中包含产品编号的列表,并在其上创建的预测,即forecasted_on的日期和它的预测是与预测一起创建了一个月数量。

每个月的数据都会在接下来的6个月内添加。因此,当预测结果为2016年1月1日时,预测将在1月至6月之间建立。

我想创建一份报告,显示过去3个月总预测的变化情况。这样

+------------+----------------+---------------+----------------+ 
|   | 0 months prior | 1 month prior | 2 months prior | 
+------------+----------------+---------------+----------------+ 
| 2016-12-01 |   200 |   150 |   250 | 
| 2017-01-01 |   300 |   250 |   150 | 
| 2017-02-01 |   100 |   150 |   100 | 
+------------+----------------+---------------+----------------+ 

事情目前我使用了很多重复的代码在轨生成此表。我想知道是否有更简单的方法直接使用SQL查询来完成它。

任何帮助将不胜感激。

回答

0

使用PIVOT查询:

select forecast_for, 
     sum(case when forecasted_on + interval '1' month = forecast_for 
      then quantity end) q_0, 
     sum(case when forecasted_on + interval '2' month = forecast_for 
      then quantity end) q_1, 
     sum(case when forecasted_on + interval '3' month = forecast_for 
      then quantity end) q_2, 
     sum(case when forecasted_on + interval '4' month = forecast_for 
      then quantity end) q_3, 
     sum(case when forecasted_on + interval '5' month = forecast_for 
      then quantity end) q_4, 
     sum(case when forecasted_on + interval '6' month = forecast_for 
      then quantity end) q_5 
from Table1 
group by forecast_for 
order by 1 
; 

演示:http://sqlfiddle.com/#!15/30e5e/1

|    forecast_for | q_0 | q_1 | q_2 | q_3 | q_4 | q_5 | 
|----------------------------|--------|--------|--------|--------|--------|--------| 
| December, 01 2016 00:00:00 | 100 | (null) | (null) | (null) | (null) | (null) | 
| January, 01 2017 00:00:00 | (null) | 200 | (null) | (null) | (null) | (null) | 
| February, 01 2017 00:00:00 | (null) | (null) | 300 | (null) | (null) | (null) | 
| March, 01 2017 00:00:00 | (null) | (null) | (null) | 400 | (null) | (null) | 
| April, 01 2017 00:00:00 | (null) | (null) | (null) | (null) | 500 | (null) | 
|  May, 01 2017 00:00:00 | (null) | (null) | (null) | (null) | (null) | 600 | 
0

假设(product_number, forcast_on, forcasted_for)是唯一的(是必需的,没有聚集),那么这应该做的工作:

WITH forecast_dates AS (
    SELECT DISTINCT product_number, forcast_for 
    FROM forecasts 
) 
SELECT 
    fd.forcast_for AS "forecast for", 
    m1.quantity AS "one month prior", 
    m2.quantity AS "two months prior", 
    m3.quantity AS "three months prior" 
FROM forecast_dates fd 
    LEFT JOIN forecasts m1 ON fd.forcast_for = m1.forcast_for AND fd.forcast_for = m1.forcasted_on + INTERVAL '1 month' 
    LEFT JOIN forecasts m2 ON fd.forcast_for = m2.forcast_for AND fd.forcast_for = m2.forcasted_on + INTERVAL '2 month' 
    LEFT JOIN forecasts m3 ON fd.forcast_for = m3.forcast_for AND fd.forcast_for = m3.forcasted_on + INTERVAL '3 month' 
WHERE fd.product_number = 'Prod 1' 
ORDER BY fd.forcast_for;