问题
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):
- Estimating number of weeks per Task
- Dividing the hours with number of weeks
- 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