2017-02-26 21 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

非常感谢!