Re: How to split normal and overtime hours

Andrus <kobruleht2@hot.ee>

From: Andrus <kobruleht2@hot.ee>
To: Torsten Förtsch <tfoertsch123@gmail.com>
Cc: pgsql-general <pgsql-general@postgresql.org>
Date: 2022-02-14T10:04:12Z
Lists: pgsql-general
Hi!

It worked.

Thank you very much.

Andrus.

13.02.2022 16:46 Torsten Förtsch kirjutas:
> WITH x AS (
>    SELECT *
>         , sum(hours) OVER w AS s
>      FROM hours
>    WINDOW w AS (PARTITION BY person ORDER BY job_id)
> )
> SELECT *
>     , greatest(least(s, 120) - coalesce(lag(s, 1) OVER w, 0), 0) AS 
> regular
>     , hours - greatest(least(s, 120) - coalesce(lag(s, 1) OVER w, 0), 
> 0) AS overtime
>  FROM x
> WINDOW w AS (PARTITION BY person ORDER BY job_id)
>
>
> On Sun, Feb 13, 2022 at 1:57 PM Andrus <kobruleht2@hot.ee> wrote:
>
>     Hi!
>
>     Thank you. In this result, regular and overtime columns contain
>     running totals.
>
>     How to fix this so that those columns contain just hours for each job?
>
>     sum on regular column should not be greater than 120 per person.
>
>     sum of regular and overtime  columns must be same as sum of hours
>     column in hours table for every person.
>
>     Andrus.
>
>     13.02.2022 14:46 Torsten Förtsch kirjutas:
>>     something like
>>
>>     SELECT *
>>          , least(sum(hours) OVER w, 120) AS regular
>>          , greatest(sum(hours) OVER w - 120, 0) AS overtime
>>       FROM hours
>>     WINDOW w AS (PARTITION BY person ORDER BY job_id);
>>
>>      job_id | person | hours | regular | overtime
>>     --------+--------+-------+---------+----------
>>           2 | bill   |    10 |      10 |        0
>>           5 | bill   |    40 |      50 |        0
>>           8 | bill   |    10 |      60 |        0
>>          10 | bill   |    70 |     120 |       10
>>          11 | bill   |    30 |     120 |       40
>>          13 | bill   |    40 |     120 |       80
>>          15 | bill   |    10 |     120 |       90
>>           4 | hugo   |    70 |      70 |        0
>>           7 | hugo   |   130 |     120 |       80
>>           1 | john   |    10 |      10 |        0
>>           3 | john   |    50 |      60 |        0
>>           6 | john   |    30 |      90 |        0
>>           9 | john   |    50 |     120 |       20
>>          12 | john   |    30 |     120 |       50
>>          14 | john   |    50 |     120 |      100
>>
>>
>>     On Sun, Feb 13, 2022 at 12:47 PM Andrus <kobruleht2@hot.ee> wrote:
>>
>>         Hi!
>>
>>         Hours table contains working hours for jobs:
>>
>>             create table hours (
>>             jobid integer primary key, -- job done, unique for person
>>             personid char(10) not null, -- person who did job
>>             hours numeric(5,2) not null -- hours worked for job
>>             )
>>
>>         Hours more than 120 are overtime hours.
>>
>>         How to split regular and overtime hours into different
>>         columns using running total by job id and partition by person id?
>>
>>         For example, if John did 3 jobs 1, 2,3 with 90, 50 and 40
>>         hours (total 180 hours) for each job correspondingly, result
>>         table should be:
>>
>>             personid    jobid  normal_hours overtime_hours
>>             john            1         90               0
>>             john            2         30              20
>>             john            3          0              40
>>
>>         sum on normal_hours column should not be greater than 120 per
>>         person.
>>
>>         sum of normal_hours and overtime_hours columns must be same
>>         as sum of hours column in hours table for every person.
>>
>>         Note that since hours running total becomes greater than 120
>>         in job 2, job 2 hours should appear in both hours columns.
>>
>>         Maybe window functions can used.
>>
>>         Andrus.
>>