From: | Adrian Klaver <adrian(dot)klaver(at)aklaver(dot)com> |
---|---|
To: | Ken Tanzer <ken(dot)tanzer(at)gmail(dot)com> |
Cc: | PG-General Mailing List <pgsql-general(at)postgresql(dot)org> |
Subject: | Re: Given a set of daterange, finding the continuous range that includes a particular date |
Date: | 2018-02-23 05:08:02 |
Message-ID: | 53425537-1378-bd5d-4362-4f5dec5b8d7a@aklaver.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
On 02/22/2018 09:05 PM, Adrian Klaver wrote:
> On 02/22/2018 05:23 PM, Ken Tanzer wrote:
>>
>>
>> On Thu, Feb 22, 2018 at 5:05 PM, Adrian Klaver
>> <adrian(dot)klaver(at)aklaver(dot)com <mailto:adrian(dot)klaver(at)aklaver(dot)com>> wrote:
>>
>> On 02/22/2018 04:58 PM, Ken Tanzer wrote:
>>
>>
>>
>> On Thu, Feb 22, 2018 at 4:53 PM, Adrian Klaver
>> <adrian(dot)klaver(at)aklaver(dot)com <mailto:adrian(dot)klaver(at)aklaver(dot)com>
>> <mailto:adrian(dot)klaver(at)aklaver(dot)com
>> <mailto:adrian(dot)klaver(at)aklaver(dot)com>>> wrote:
>>
>> On 02/22/2018 04:44 PM, Ken Tanzer wrote:
>>
>> Hi, hoping to get some help with this. I'm needing to
>> take a
>> specific date, a series of dateranges and, given a
>> specific
>> date, return a single conitinuous daterange that
>> includes that date.
>>
>> To elaborate a bit, I've got lots of tables that
>> include start
>> and end dates. For example:
>>
>> CREATE TABLE tbl_staff_assign (
>> staff_assign_id SERIAL PRIMARY KEY,
>> client_id INTEGER NOT NULL
>> REFERENCES
>> tbl_client (client_id),
>> staff_id INTEGER REFERENCES
>> tbl_staff(staff_id),
>> staff_assign_type_code VARCHAR(10) NOT NULL
>> REFERENCES tbl_l_staff_assign_type
>> (staff_assign_type_code),
>> staff_assign_date DATE NOT NULL,
>> staff_assign_date_end DATE,
>> ...
>>
>> So a client might leave a progrma and then return
>> later, or they
>> might simply switch to another staff_id. (In which
>> case one
>> record will have and end date, and the next record will
>> start on
>> the next day.) In this case I need to know "what
>> period were
>> they continuously in the program that includes X date?"
>> So I'd
>> like to be able to do something like:
>>
>> "SELECT staff_assign_date,continuous_daterange(
>> staff_assign_date, (SELECT
>> array_agg(daterange(staff_assign_date,staff_assign_date_end,'[]')
>> ) FROM staff_assign sa2 WHERE
>> sa2.client_id=sa.client_id) FROM
>> staff_assign sa
>>
>> I've done this before with procedures specific to a
>> particular
>> table, and working with the start and end dates. I'm
>> now
>> wanting to try to do this once generically that will
>> work for
>> all my cases. So I'm hoping to do this in a way that
>> performance isn't horrible. And it's a little unclear
>> to me how
>> much and how I might be able to use the daterange
>> operators to
>> accomplish this efficiently.
>>
>>
>> The operator I use to solve similar problems:
>>
>> https://www.postgresql.org/docs/10/static/functions-range.html
>> <https://www.postgresql.org/docs/10/static/functions-range.html>
>> <https://www.postgresql.org/docs/10/static/functions-range.html
>> <https://www.postgresql.org/docs/10/static/functions-range.html>>
>>
>> @> contains element
>> '[2011-01-01,2011-03-01)'::tsrange
>> @> '2011-01-10'::timestamp t
>>
>>
>> Thanks Adrian. But how would you apply that to this situation,
>> where I have a series of (quite possibly discontinuous)
>> dateranges?
>>
>>
>> This is going to depend on a more formal definition of the problem
>> with some sample data. Right now I am trying to reconcile "what
>> period were they continuously in the program that includes X date?"
>> with "where I have a series of (quite possibly discontinuous)
>> dateranges? " Maybe its just me, I can't see how discontinuous can
>> also be continuously.
>>
>>
>>
>> *Start End*
>> -- Episode 1
>> 1/1/16 3/30/16
>> 4/1/16 4/30/16
>> -- Episode 2
>> 1/1/18 1/31/18
>> 2/1/18 NULL
>>
>> Given 1/15/18, should return 1/1/18-->NULL
>> Given 1/15/16, should return 1/1/16-->4/30/16
>
> Just thinking out loud here, in a function:
>
> 1) For a client_id you can find the min(staff_assign_date).
>
> 2) You can create a max(staff_assign_date_end) by using
> COALESCE(staff_assign_date_end, current_date)
>
> 3) You now have the outer range for the episodes.
>
> 4) In that range of dates for each staff_assign_date you find the
> staff_assign_date_end that greater then the staff_assign_date but less
> then the next staff_assign_date. That will give you your episodes.
>
> 5) You can then test to see if the X date is in the calculated episodes.
>
> 6) As a shortcut you can find min(staff_assign_date) that is less then
> the X date and see if the staff_assign_date_end is greater then the X date.
>
Correction to 6)
6) As a shortcut you can find max(staff_assign_date) that is less then
the X date and see if the staff_assign_date_end is greater then the X date.
--
Adrian Klaver
adrian(dot)klaver(at)aklaver(dot)com
From | Date | Subject | |
---|---|---|---|
Next Message | Paul Jungwirth | 2018-02-23 05:45:51 | Re: Given a set of daterange, finding the continuous range that includes a particular date |
Previous Message | Adrian Klaver | 2018-02-23 05:05:41 | Re: Given a set of daterange, finding the continuous range that includes a particular date |