从间隔中拆分值并按 isoweek 分组 - Postgresql

Split values from an interval and group by isoweek - Postgresql

我想根据日期间隔将 "distribute" 或 "split" 小时从单个任务转换为 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);

这 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 周对结果进行分组
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 查询以获取开始和结束年份并计算跨年的周数。

根据帕特里克的回答,我找到了这个解决方案:

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

非常感谢!