work hour calculations

Started by noviceover 18 years ago7 messagesgeneral
Jump to latest
#1novice
user.postgresql@gmail.com

Hello All,

SELECT notification_time, finished_time, sum(finished_time -
notification_time) as actual
FROM log
GROUP BY notification_time, finished_time;

gives me:

notification_time | finished_time | actual
------------------------+------------------------+-----------------
2007-07-06 15:50:00+10 | 2007-07-09 07:10:00+10 | 2 days 15:20:00
2007-07-07 12:30:00+10 | 2007-07-09 07:20:00+10 | 1 day 18:50:00

How can write a query to calculate the duration using custom work
hours which is Monday 7am / Friday 5pm?

The result I'm expecting for the above to be

notification_time | finished_time | actual
------------------------+------------------------+-----------------
2007-07-06 15:50:00+10 | 2007-07-09 07:10:00+10 | 00:20:00
2007-07-07 12:30:00+10 | 2007-07-09 07:20:00+10 | 00:20:00

Thanks.

#2Raj A
raj.ayappan@gmail.com
In reply to: novice (#1)
Re: work hour calculations

correction:

Show quoted text

The result I'm expecting for the above to be

notification_time | finished_time | actual
------------------------+------------------------+-----------------
2007-07-06 15:50:00+10 | 2007-07-09 07:10:00+10 | 01:20:00
2007-07-07 12:30:00+10 | 2007-07-09 07:20:00+10 | 00:20:00

#3novice
user.postgresql@gmail.com
In reply to: Raj A (#2)
Re: work hour calculations

correction:

The result I'm expecting for the above to be

notification_time | finished_time | actual
------------------------+------------------------+-----------------

2007-07-06 15:50:00+10 | 2007-07-09 07:10:00+10 | 01:20:00

Show quoted text

2007-07-07 12:30:00+10 | 2007-07-09 07:20:00+10 | 00:20:00

#4A. Kretschmer
andreas.kretschmer@schollglas.com
In reply to: novice (#1)
Re: work hour calculations

am Wed, dem 05.09.2007, um 13:45:46 +1000 mailte novice folgendes:

Hello All,

SELECT notification_time, finished_time, sum(finished_time -
notification_time) as actual
FROM log
GROUP BY notification_time, finished_time;

gives me:

notification_time | finished_time | actual
------------------------+------------------------+-----------------
2007-07-06 15:50:00+10 | 2007-07-09 07:10:00+10 | 2 days 15:20:00
2007-07-07 12:30:00+10 | 2007-07-09 07:20:00+10 | 1 day 18:50:00

How can write a query to calculate the duration using custom work
hours which is Monday 7am / Friday 5pm?

The result I'm expecting for the above to be

notification_time | finished_time | actual
------------------------+------------------------+-----------------
2007-07-06 15:50:00+10 | 2007-07-09 07:10:00+10 | 00:20:00
2007-07-07 12:30:00+10 | 2007-07-09 07:20:00+10 | 00:20:00

You can write a function. Calculate for every day between
notification_time and finished_time this timestamps for every day. I
mean, for instance your first row:

2007-07-06 15:50:00+10 2007-07-07 00:00:00+10
2007-07-07 00:00:00+10 2007-07-08 00:00:00+10
2007-07-08 00:00:00+10 2007-07-09 00:00:00+10
2007-07-09 00:00:00+10 2007-07-09 07:20:00+10

Now check, if the first timestamp are a working day (select
extract('dow' from '2007-07-06 15:50:00+10'::timestamptz)). If so, than
calculate the working-time and adds all.

A little function for you:

<--- cut
create or replace function intersect_time (IN start timestamptz, IN stop timestamptz, IN w_start timestamptz, IN w_end timestamptz, OUT duration interval) as $$
declare
_s1 alias for $1;
_e1 alias for $2;
_s2 alias for $3;
_e2 alias for $4;
_start timestamptz;
_end timestamptz;

begin

if _s1 < _s2 then
_start := _s2;
else
_start := _s1;
end if;

if _e1 < _e2 then
_end := _e1;
else
_end := _e2;
end if;

if _start < _end then
duration := _end - _start;
else
duration := '0'::interval;
end if;

return;

end;
$$language plpgsql;

--- cut

A simple test:

Only the first and the last are working days, so we call the function
for this rows:

test=*# select intersect_time('2007-07-06 15:50:00+10'::timestamptz,'2007-07-07 00:00:00+10'::timestamptz, '2007-07-06 07:00:00+10'::timestamptz, '2007-07-06 17:00:00+10'::timestamptz);
intersect_time
----------------
01:10:00
(1 row)

test=*# select intersect_time('2007-07-09 00:00:00+10'::timestamptz,'2007-07-09 07:10:00+10'::timestamptz, '2007-07-09 07:00:00+10'::timestamptz, '2007-07-09 17:00:00+10'::timestamptz);
intersect_time
----------------
00:10:00
(1 row)

test=*# select '01:10:00'::interval + '00:10:00'::interval;
?column?
----------
01:20:00
(1 row)

Hope that helps, Andreas
--
Andreas Kretschmer
Kontakt: Heynitz: 035242/47150, D1: 0160/7141639 (mehr: -> Header)
GnuPG-ID: 0x3FFF606C, privat 0x7F4584DA http://wwwkeys.de.pgp.net

#5Filip Rembiałkowski
plk.zuber@gmail.com
In reply to: Raj A (#2)
Re: work hour calculations

2007/9/5, Raj A <raj.ayappan@gmail.com>:

correction:

The result I'm expecting for the above to be

notification_time | finished_time | actual
------------------------+------------------------+-----------------
2007-07-06 15:50:00+10 | 2007-07-09 07:10:00+10 | 01:20:00
2007-07-07 12:30:00+10 | 2007-07-09 07:20:00+10 | 00:20:00

Could you please show the data structures ( create table commmands +
ane constraints you have )?

If you do this, you have much bigger chance of getting an answer :)

--
Filip Rembiałkowski

#6novice
user.postgresql@gmail.com
In reply to: Filip Rembiałkowski (#5)
Re: work hour calculations

On 07/09/2007, Filip Rembiałkowski <plk.zuber@gmail.com> wrote:

2007/9/5, Raj A <raj.ayappan@gmail.com>:

correction:

The result I'm expecting for the above to be

notification_time | finished_time | actual
------------------------+------------------------+-----------------
2007-07-06 15:50:00+10 | 2007-07-09 07:10:00+10 | 01:20:00
2007-07-07 12:30:00+10 | 2007-07-09 07:20:00+10 | 00:20:00

Could you please show the data structures ( create table commmands +
ane constraints you have )?

If you do this, you have much bigger chance of getting an answer :)

sure

create table log
(
id integer PRIMARY KEY,
notification_time timestamp with time zone,
finished_time timestamp with time zone
);

INSERT INTO log values (1, '2007-07-06 15:50', '2007-07-09 07:10');
INSERT INTO log values (2, '2007-07-07 12:30', '2007-07-09 07:20');

SELECT notification_time, finished_time, sum(finished_time -
notification_time) as actual
FROM log
GROUP BY notification_time, finished_time;

#7Filip Rembiałkowski
plk.zuber@gmail.com
In reply to: novice (#6)
Re: work hour calculations

2007/9/9, novice <user.postgresql@gmail.com>:

The result I'm expecting for the above to be

notification_time | finished_time | actual
------------------------+------------------------+-----------------
2007-07-06 15:50:00+10 | 2007-07-09 07:10:00+10 | 01:20:00
2007-07-07 12:30:00+10 | 2007-07-09 07:20:00+10 | 00:20:00

create table log
(
id integer PRIMARY KEY,
notification_time timestamp with time zone,
finished_time timestamp with time zone
);

INSERT INTO log values (1, '2007-07-06 15:50', '2007-07-09 07:10');
INSERT INTO log values (2, '2007-07-07 12:30', '2007-07-09 07:20');

SELECT notification_time, finished_time, sum(finished_time -
notification_time) as actual
FROM log
GROUP BY notification_time, finished_time;

OK. so I have bad news for you: with such structure, you will have to
write some function to calculate work time spent for each task.

general algorithm would be similar to

* take the notification time
* take the finished_time
* set pointer := notif. time
* set actual := 0
* while there is any weekend between the pointer and finished_time,
do the following
** set actual := actual + ( weekend begin - pointer )
** move pointer to the next monday morning
* set actual := actual + ( finished_time - pointer )

BUT:
this is ugly.
do you always assume that people are doing ONLY one task at a time?

maybe think of representing work sheets in the database?

maybe think of adding "work_time" field to your table (why not trust
people, they know best)

maybe the application you use for entering data could give some "hint"
basing on above algo.

good luck,

--
Filip Rembiałkowski