pg.ddx.io  pgsql-sql@postgresql.org mailing list archive  
help / color / mirror / Atom feed
Intersection of two date interval
4+ messages / 4 participants
[nested] [flat]

* Intersection of two date interval
@ 2007-01-26 09:39 Suha Onay <suhaonay@gmail.com>
  2007-01-26 09:50 ` Re: Intersection of two date interval A. Kretschmer <andreas.kretschmer@schollglas.com>
  0 siblings, 1 reply; 4+ messages in thread

From: Suha Onay @ 2007-01-26 09:39 UTC (permalink / raw)
  To: pgsql-sql

Hi,

How can i find the number of days in the intersection of 2 date interval?
For example:
1st  interval: (10.01.2007, 20.01.2007)
2nd interval: (13.01.2007, 21.01.2007)
The intersection dates are: 13,14,15,16,17,18,19, 20
The result is: 8

How can i find the result, 8 in an sql query without using CASE statements?

Table columns are id PK, date1 date, date2 date.

Thanks for all your help.


Suha

^ permalink  raw  reply  [nested|flat] 4+ messages in thread

* Re: Intersection of two date interval
  2007-01-26 09:39 Intersection of two date interval Suha Onay <suhaonay@gmail.com>
@ 2007-01-26 09:50 ` A. Kretschmer <andreas.kretschmer@schollglas.com>
  2007-01-26 10:02   ` Re: Intersection of two date interval Achilleas Mantzios <achill@matrix.gatewaynet.com>
  0 siblings, 1 reply; 4+ messages in thread

From: A. Kretschmer @ 2007-01-26 09:50 UTC (permalink / raw)
  To: pgsql-sql

am  Fri, dem 26.01.2007, um 11:39:03 +0200 mailte Suha Onay folgendes:
> Hi,
> 
> How can i find the number of days in the intersection of 2 date interval?
> For example:
> 1st  interval: (10.01.2007, 20.01.2007)
> 2nd interval: (13.01.2007, 21.01.2007)
> The intersection dates are: 13,14,15,16,17,18,19, 20
> The result is: 8
> 
> How can i find the result, 8 in an sql query without using CASE statements?


Some time ago i wrote a function for this, i hope it's helpfull for you:
(not realy tested, be careful!)



create type start_end as (t1 timestamptz, t2 timestamptz);

create or replace function time_intersect (timestamptz, timestamptz, timestamptz, timestamptz) returns start_end as $$
declare
        _s1     alias for $1;
        _e1     alias for $2;
        _s2     alias for $3;
        _e2     alias for $4;
        _start  timestamptz;
        _end    timestamptz;
        _return start_end;
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
                _return.t1 := _start;
                _return.t2 := _end;
        else
                _return.t1 := NULL;
                _return.t2 := NULL;
        end if;

        return _return;
end
$$ language plpgsql;


test=# set datestyle=german;
SET
test=*# select time_intersect('10.01.2007'::date, '20.01.2007'::date, '13.01.2007'::date, '21.01.2007'::date);
                    time_intersect
-------------------------------------------------------
 ("13.01.2007 00:00:00 CET","20.01.2007 00:00:00 CET")
(1 row)


test=*# select *, t2-t1 from time_intersect('10.01.2007'::date, '20.01.2007'::date, '13.01.2007'::date, '21.01.2007'::date);
           t1            |           t2            | ?column?
-------------------------+-------------------------+----------
 13.01.2007 00:00:00 CET | 20.01.2007 00:00:00 CET | @ 7 days
(1 row)




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



^ permalink  raw  reply  [nested|flat] 4+ messages in thread

* Re: Intersection of two date interval
  2007-01-26 09:39 Intersection of two date interval Suha Onay <suhaonay@gmail.com>
  2007-01-26 09:50 ` Re: Intersection of two date interval A. Kretschmer <andreas.kretschmer@schollglas.com>
@ 2007-01-26 10:02   ` Achilleas Mantzios <achill@matrix.gatewaynet.com>
  2007-01-26 20:11     ` Re: Intersection of two date interval Bruno Wolff III <bruno@wolff.to>
  0 siblings, 1 reply; 4+ messages in thread

From: Achilleas Mantzios @ 2007-01-26 10:02 UTC (permalink / raw)
  To: pgsql-sql

Στις Παρασκευή 26 Ιανουάριος 2007 11:50, ο/η A. Kretschmer έγραψε:
> am  Fri, dem 26.01.2007, um 11:39:03 +0200 mailte Suha Onay folgendes:
> > Hi,
> >
> > How can i find the number of days in the intersection of 2 date interval?
> > For example:
> > 1st  interval: (10.01.2007, 20.01.2007)
> > 2nd interval: (13.01.2007, 21.01.2007)
> > The intersection dates are: 13,14,15,16,17,18,19, 20
> > The result is: 8
> >
> > How can i find the result, 8 in an sql query without using CASE
> > statements?
>
> Some time ago i wrote a function for this, i hope it's helpfull for you:
> (not realy tested, be careful!)
>
>
>
> create type start_end as (t1 timestamptz, t2 timestamptz);
>
> create or replace function time_intersect (timestamptz, timestamptz,
> timestamptz, timestamptz) returns start_end as $$ declare
>         _s1     alias for $1;
>         _e1     alias for $2;
>         _s2     alias for $3;
>         _e2     alias for $4;
>         _start  timestamptz;
>         _end    timestamptz;
>         _return start_end;
> 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
>                 _return.t1 := _start;
>                 _return.t2 := _end;
>         else
>                 _return.t1 := NULL;
>                 _return.t2 := NULL;
>         end if;
>
>         return _return;
> end
> $$ language plpgsql;
>
>

Suha,
the function is the number of days in the 
maximum of the two start dates , untill , minimum of the two end dates 
interval.
But in postgresql (7.4.15 at least) there is no MIN(date,date),MAX(date,date) 
functions. So someone has to write them, so you cant avoid some logic there.
Whats your problem with "CASE" statements?
what you are basically looking for is smth like the above implementation
from Andreas.

> test=# set datestyle=german;
> SET
> test=*# select time_intersect('10.01.2007'::date, '20.01.2007'::date,
> '13.01.2007'::date, '21.01.2007'::date); time_intersect
> -------------------------------------------------------
>  ("13.01.2007 00:00:00 CET","20.01.2007 00:00:00 CET")
> (1 row)
>
>
> test=*# select *, t2-t1 from time_intersect('10.01.2007'::date,
> '20.01.2007'::date, '13.01.2007'::date, '21.01.2007'::date); t1           
> |           t2            | ?column?
> -------------------------+-------------------------+----------
>  13.01.2007 00:00:00 CET | 20.01.2007 00:00:00 CET | @ 7 days
> (1 row)
>
>
>
>
> Andreas

-- 
Achilleas Mantzios



^ permalink  raw  reply  [nested|flat] 4+ messages in thread

* Re: Intersection of two date interval
  2007-01-26 09:39 Intersection of two date interval Suha Onay <suhaonay@gmail.com>
  2007-01-26 09:50 ` Re: Intersection of two date interval A. Kretschmer <andreas.kretschmer@schollglas.com>
  2007-01-26 10:02   ` Re: Intersection of two date interval Achilleas Mantzios <achill@matrix.gatewaynet.com>
@ 2007-01-26 20:11     ` Bruno Wolff III <bruno@wolff.to>
  0 siblings, 0 replies; 4+ messages in thread

From: Bruno Wolff III @ 2007-01-26 20:11 UTC (permalink / raw)
  To: Achilleas Mantzios <achill@matrix.gatewaynet.com>; +Cc: pgsql-sql

On Fri, Jan 26, 2007 at 12:02:24 +0200,
  Achilleas Mantzios <achill@matrix.gatewaynet.com> wrote:
> Suha,
> the function is the number of days in the 
> maximum of the two start dates , untill , minimum of the two end dates 
> interval.
> But in postgresql (7.4.15 at least) there is no MIN(date,date),MAX(date,date) 
> functions. So someone has to write them, so you cant avoid some logic there.
> Whats your problem with "CASE" statements?
> what you are basically looking for is smth like the above implementation
> from Andreas.

Postgres (at least since 8.1) has GREATEST and LEAST and they provide the
needed functions.
And you should be able to subtract two dates (not timestamps) to get an
integer. (And to count the number of days rather than the time between, you
need to add 1.)
You also will want to put a floor on the overlap so that you don't get
negative values.
So in your case the query would look something like:

bruno=> SELECT GREATEST(0, LEAST('2007-01-20'::date, '2007-01-21'::date) -
bruno(> GREATEST('2007-01-10'::date, '2007-01-13'::date) + 1);
 greatest
----------
        8
(1 row)



^ permalink  raw  reply  [nested|flat] 4+ messages in thread


end of thread, other threads:[~2007-01-26 20:11 UTC | newest]

Thread overview: 4+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2007-01-26 09:39 Intersection of two date interval Suha Onay <suhaonay@gmail.com>
2007-01-26 09:50 ` A. Kretschmer <andreas.kretschmer@schollglas.com>
2007-01-26 10:02   ` Achilleas Mantzios <achill@matrix.gatewaynet.com>
2007-01-26 20:11     ` Bruno Wolff III <bruno@wolff.to>

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox