2016-11-23 116 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;