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:05:41 |
Message-ID: | 9149730a-55ab-7a2f-6a06-85d9be2eaa4b@aklaver.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
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.
>
> Thinking about this a bit more, I'm wondering if a window function could
> be used for this? I've used them a bit, but definitely never wrote one.
> Something like
>
> continuous_daterange(staff_assign_date,daterange(staff_assign_date,staff_assign_date_end,'[[]')
> OVER (PARTION BY client_id)
>
> But then a window function can only see the rows included in the query,
> yes? In which case this would only work if you queried for all the rows
> for a particular client_id? I guess in the example I gave I was doing
> that anyway, so maybe this would be no worse.
>
> Ken
> --
> AGENCY Software
> A Free Software data system
> By and for non-profits
> /http://agency-software.org//
> /https://demo.agency-software.org/client/
> ken(dot)tanzer(at)agency-software(dot)org <mailto:ken(dot)tanzer(at)agency-software(dot)org>
> (253) 245-3801
>
> Subscribe to the mailing list
> <mailto:agency-general-request(at)lists(dot)sourceforge(dot)net?body=subscribe> to
> learn more about AGENCY or
> follow the discussion.
--
Adrian Klaver
adrian(dot)klaver(at)aklaver(dot)com
From | Date | Subject | |
---|---|---|---|
Next Message | Adrian Klaver | 2018-02-23 05:08:02 | Re: Given a set of daterange, finding the continuous range that includes a particular date |
Previous Message | Vinodh NV | 2018-02-23 04:43:01 | Postgres hangs for the query "lock table <Tablename> in exclusive mode" |