通过isoweek - Postgresql从间隔和组中拆分值

时间:2017-02-26 11:15:34

标签: postgresql postgresql-9.1

我想"分发"或"拆分"从单个任务到基于日期间隔的iso周的小时数。但我不知道如何在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);

这两项任务的理想输出应该是:

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周

2 个答案:

答案 0 :(得分: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() set-returning函数将其转换为一组行,每周一行。然后,主查询计算每周每项任务的小时数。

请注意,这在多年内不起作用。如果您需要,那么您必须展开sub查询以获取开始和停止年份并计算多年的周数。

答案 1 :(得分:0)

根据Patricks的回答,我找到了这个解决方案:

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

非常感谢!