2017-02-26 50 views
2

我想根據日期間隔將單個任務「分配」或「拆分」幾小時到iso周。但我不知道如何在Postgresql中做到這一點。從isoweek中間隔和組中拆分值 - Postgresql

CREATE TABLE task 
    (id int4, start date, stop date, hr int4);  
INSERT INTO task 
    (id, start, stop, hr) 
VALUES 
    (1, '2017-01-01','2017-01-31', 80), 
    (2, '2017-01-01','2017-02-28', 120); 

的這些2個任務所需的輸出應該是這樣的:

The 80 hr of task 1 should be distributed into 5 weeks 

201701 16 hr 
201702 16 hr 
201703 16 hr 
201704 16 hr 
201705 16 hr 

The 120 hr of task 2 should be distributed into 9 weeks 

201701 13,3 hr 
201702 13,3 hr 
201703 13,3 hr 
201704 13,3 hr 
201705 13,3 hr 
201706 13,3 hr 
201707 13,3 hr 
201708 13,3 hr 
201709 13,6 hr 

這估計是一個粗略的估計,並且可以從現實不同。

我能想到的三個步驟(和無法弄清楚如何):

  1. 估計週數每任務
  2. 與周
  3. 分組這樣的結果通過ISO周
  4. 數除以小時

回答

1
SELECT id, 
     yr * 100 + w AS week, 
     hr::double precision/(stop_week - start_week + 1) AS hrs_per_week 
FROM (
    SELECT id, 
      extract(year from start)::integer AS yr, 
      extract(week from start)::integer AS start_week, 
      extract(week from stop)::integer AS stop_week, 
      hr 
    FROM task) sub, 
    generate_series(start_week, stop_week) weeks(w) 
ORDER BY 1, 2; 

sub查詢從每行的一些基本數據被收集時,generate_series()設置返回函數將其轉換爲每週一行的一組行。主查詢然後計算每週每個任務的小時數。

請注意,這不適用於多年。如果您需要,則必須擴大sub查詢以獲取開始和停止年份並計算跨越幾年的週數。

+0

謝謝,但是他給出了一個空的結果:http://sqlfiddle.com/#!15/93ee1/12我需要ISO周。 – sibert

+0

是的,這是ISO周的棘手的東西。 2017-01-01屬於ISO 2016年第52周,而'generate_series(52,5)'產生一組空行。如果從1月到3月更改表格中的日期,則查詢工作得很好。 – Patrick

0

基於帕特里克的答案,我發現這個解決方案:

SELECT id,to_char(iso, 'iyyy-iw'),(hr/weeks)::numeric (5,2) as hr_week 
FROM (SELECT id,hr,generate_series(start,stop,interval '1 week') as iso, 
(stop - start)/7 as weeks FROM task) as sub 

http://sqlfiddle.com/#!15/93ee1/78

非常感謝!