Re: View - Mailing list pgsql-novice

From Michael Fuhr
Subject Re: View
Date
Msg-id 20050926034039.GA11819@winnie.fuhr.org
Whole thread Raw
In response to View  (A Gilmore <agilmore@shaw.ca>)
Responses Re: View
List pgsql-novice
On Sat, Sep 24, 2005 at 12:11:09PM -0700, A Gilmore wrote:
> So I have event bookings, then if they use some kind of recurrence, its
> stored in myRecurrence.  This has worked fine, since sorting out
> recurring dates (creating the duplicate events) is all done client-side
> based on these entries.
>
> However now I need the server to be aware of recurring dates.  So if an
> event is booked, then to recur each month for 5 months, Id have 5
> entires show up in my SELECT.

You might be able to use generate_series() (a standard set-returning
function in 8.0, and trivial to write in earlier versions).  Here's
a simplified example based on what you posted; it might be close
to what you're looking for:

CREATE TABLE event (
    id    integer PRIMARY KEY,
    date  date NOT NULL
);

CREATE TABLE recurrence (
    id       integer PRIMARY KEY,
    eventid  integer NOT NULL REFERENCES event,
    num      integer NOT NULL CHECK (num > 0),
    freq     interval NOT NULL
);

INSERT INTO event (id, date) VALUES (1, '2005-01-01');
INSERT INTO event (id, date) VALUES (2, '2005-02-02');
INSERT INTO event (id, date) VALUES (3, '2005-03-03');

INSERT INTO recurrence (id, eventid, num, freq) VALUES (1, 2, 2, '1 week');
INSERT INTO recurrence (id, eventid, num, freq) VALUES (2, 3, 5, '1 month');

SELECT e.id,
       e.date AS origdate,
       r.num,
       r.freq,
       (e.date + generate_series(0, coalesce(r.num - 1, 0))
                 * coalesce(r.freq, '1 day'))::date AS recurdate
FROM event AS e
LEFT OUTER JOIN recurrence AS r ON r.eventid = e.id
ORDER by e.id, recurdate;

 id |  origdate  | num |  freq  | recurdate
----+------------+-----+--------+------------
  1 | 2005-01-01 |     |        | 2005-01-01
  2 | 2005-02-02 |   2 | 7 days | 2005-02-02
  2 | 2005-02-02 |   2 | 7 days | 2005-02-09
  3 | 2005-03-03 |   5 | 1 mon  | 2005-03-03
  3 | 2005-03-03 |   5 | 1 mon  | 2005-04-03
  3 | 2005-03-03 |   5 | 1 mon  | 2005-05-03
  3 | 2005-03-03 |   5 | 1 mon  | 2005-06-03
  3 | 2005-03-03 |   5 | 1 mon  | 2005-07-03
(8 rows)

Note that the documentation says that using a set-returning function
in the select list is deprecated and might not work in future
versions of PostgreSQL.  It does work in 8.0.3 and 8.1beta2, but
for forward compatibility you might want to write a function to do
the iteration unless somebody posts an alternative.

--
Michael Fuhr

pgsql-novice by date:

Previous
From: Martin Foster
Date:
Subject: Re: Trouble with an outer join
Next
From: Sten Daniel Sørsdal
Date:
Subject: Custom security through functions.