Received: from maia.hub.org (maia-3.hub.org [200.46.204.243]) by mail.postgresql.org (Postfix) with ESMTP id 75CCAB5DBBE for ; Sat, 11 Jun 2011 19:18:30 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.243]) (amavisd-maia, port 10024) with ESMTP id 60794-05 for ; Sat, 11 Jun 2011 22:18:23 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from fusion.bennyvision.com (fusion.bennyvision.com [207.158.15.45]) by mail.postgresql.org (Postfix) with ESMTP id 009CDB5D80A for ; Sat, 11 Jun 2011 19:18:22 -0300 (ADT) Received: from webmail.stinkweasel.net (localhost [127.0.0.1]) by fusion.bennyvision.com (Postfix) with ESMTP id E98D51E87A6 for ; Sat, 11 Jun 2011 17:18:21 -0500 (CDT) Received: from 173.28.21.46 (SquirrelMail authenticated user benny) by webmail.stinkweasel.net with HTTP; Sat, 11 Jun 2011 17:18:21 -0500 Message-ID: Date: Sat, 11 Jun 2011 17:18:21 -0500 Subject: Re: Returning a set of dates From: "C. Bensend" To: pgsql-sql@postgresql.org User-Agent: SquirrelMail/1.4.21 MIME-Version: 1.0 Content-Type: text/plain;charset=iso-8859-1 Content-Transfer-Encoding: 8bit X-Priority: 3 (Normal) Importance: Normal X-Virus-Scanned: clamav-milter 0.96.1 at fusion.bennyvision.com X-Virus-Status: Clean X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-1.91 tagged_above=-5 required=5 tests=BAYES_00=-1.9, T_RP_MATCHES_RCVD=-0.01 X-Spam-Level: X-Archive-Number: 201106/41 X-Sequence-Number: 35507 > http://www.postgresql.org/docs/8.4/interactive/plpgsql-control-structures.html#PLPGSQL-STATEMENTS-RETURNING > >CREATE OR REPLACE FUNCTION public.next_bill_date(d date, period >interval, > i interval) > RETURNS SETOF date > AS $function$ > DECLARE > max_date date; > due_date date; > BEGIN > max_date := CURRENT_DATE + i; > due_date := d; > WHILE due_date + period <= max_date LOOP > RETURN NEXT due_date; -- add d to the result set > due_date := due_date + period; > END LOOP; > RETURN; -- exit function > END; > $function$ language plpgsql; > testdb=# select next_bill_date('2011-06-11', '2 week', '3 month'); next_bill_date > ---------------- > 2011-06-11 > 2011-06-25 > 2011-07-09 > 2011-07-23 > 2011-08-06 > 2011-08-20 Almost, but not quite - the d parameter is a bill's "start date", and the function shouldn't show dates in the past. So, when the above function is called with say '2011-06-01' as the beginning date, the function will happily return '2011-06-01' in the result set, even though it's in the past. I've modified it a bit. I renamed the function arguments to be a bit more descriptive, did a little more math, and added an IF statement to not return any dates in the past: CREATE OR REPLACE FUNCTION public.next_bill_date(d date, frequency interval, daterange interval) RETURNS SETOF date AS $function$ DECLARE max_date date; due_date date; BEGIN -- We need to add the epoch date and daterange together, to -- get the "max_date" value. However, this would cause us -- to lose the last due date in the result set. Add one more -- frequency to it so we don't lose that. max_date := CURRENT_DATE + frequency + daterange; due_date := d; WHILE due_date + frequency <= max_date LOOP -- Don't include dates in the past - we only want future -- due dates for bills. IF due_date >= CURRENT_DATE THEN RETURN NEXT due_date; END IF; due_date := due_date + frequency; END LOOP; RETURN; -- exit function This appears to work properly: SELECT next_bill_date( '2011-06-01', '2 weeks', '3 months' ); next_bill_date ---------------- 2011-06-15 2011-06-29 2011-07-13 2011-07-27 2011-08-10 2011-08-24 2011-09-07 (7 rows) Thanks for all your help! I'm not at all experienced with plpgsql, so this was very much appreciated. :) Benny -- "You were doing well until everyone died." -- "God", Futurama