Split values from an interval and group by isoweek - Postgresql

≯℡__Kan透↙ 提交于 2020-01-04 09:18:05

问题


I want to "distribute" or "split" hours from a single task into iso weeks based on a date interval. But I do not have a clue how to do this in 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 desired output of these 2 tasks should be like:

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

This estimate is a rough estimate and can differ from reality.

I can think of three steps (and cannot figure out how):

  1. Estimating number of weeks per Task
  2. Dividing the hours with number of weeks
  3. Grouping this result by iso weeks

回答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;

In the sub query some basic data from each row are collected, the generate_series() set-returning function turns that into a set of rows with one row for each week. The main query then computes the hours for each task per week.

Note that this does not work across years. If you need that, then you have to expand the sub query to get the start and stop years and calculate the number of weeks across years.




回答2:


Based on Patricks answer I found this solution:

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

Thanks a lot!



来源:https://stackoverflow.com/questions/42467770/split-values-from-an-interval-and-group-by-isoweek-postgresql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!