Re: Query help

From: Chuck Martin <clmartin(at)theombudsman(dot)com>
To: "Peter J(dot) Holzer" <hjp-pgsql(at)hjp(dot)at>
Cc: pgsql-general(at)lists(dot)postgresql(dot)org
Subject: Re: Query help
Date: 2019-01-27 22:27:26
Message-ID: CAFw6=U3ENYoeQEfwndgRWvrUe0VgL4Q4ajuRt=0qp8CSYoER-w@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On Sun, Jan 27, 2019 at 8:07 AM Peter J. Holzer <hjp-pgsql(at)hjp(dot)at> wrote:

> On 2019-01-26 18:04:23 -0500, Chuck Martin wrote:
> [snip]
> > The idea should be obvious, but to explain, insdatetime is set when a new
> > record is created in any table. All records in ombcase have a foreign
> key to
> > status that can't be null. When status changes, a record is created in
> > statuschange recording the old and new status keys, and the time (etc).
> >
> > The goal is to find records in ombcase that have not had a status change
> in xx
> > days. If the status has not changed, there will be no statuschange
> record.
>
> The easiest way is to use set operations:
>
> select case_pkey from ombcase;
> gives you all the ombcase ids.
>
> select ombcase_fkey from statuschange where insdatetime >= now()::date -
> xx;
> gives you all ombcase ids which had a status change in the last xx days.
>
> Therefore,
> select case_pkey from ombcase
> except
> select ombcase_fkey from statuschange where insdatetime >= now()::date -
> xx;
> gives you all ombcase ids which did /not/ have a status change in the
> last xx days.
>

I was not familiar with set operations, but studied up a bit and thought I
was getting there. Not quite, though. I have two queries that individually
return 1) all ombcase records with no statuschange record, and 2) the
newest statuschange record for each case that has a statuschange record.
But just putting UNION between then doesn't work. Here are my queries:

--First, find all open cases with no statuschange record
SELECT

case_pkey,statuschange_pkey,case_fkey,ombcase.insdatetime,statuschange.insdatetime
FROM
ombcase
LEFT JOIN
statuschange
ON
statuschange.case_fkey = case_pkey
AND case_pkey <> 0
LEFT JOIN
status
ON status_fkey = status_pkey
WHERE lower(statusid) NOT LIKE ('closed%')
AND statuschange.statuschange_pkey IS NULL
UNION
--Now find the last status change record for each case that has one
SELECT DISTINCT ON (case_fkey)

case_pkey,statuschange_pkey,case_fkey,ombcase.insdatetime,statuschange.insdatetime
FROM
statuschange,ombcase,status
WHERE case_fkey = case_pkey
AND status_fkey = status_pkey
AND LOWER(statusid) NOT LIKE ('closed%')
ORDER BY case_fkey, statuschange.insdatetime DESC

If I run each part separately, I get the expected number of records.
When I combine them with UNION, I get "missing FROM-clause entry for
table "statuschange"
So I'm very close here, and these two return the exact number of
records I'm expecting. So I just need to get them added together. Then
I expect I can put the whole thing in a WHERE clause with "AND
ombcase.case_pkey IN ([the combined results])"

>
> Another way would be to use a CTE
> (https://www.postgresql.org/docs/10/queries-with.html) to extract the
> last status change for each ombcase and then do a left join of ombcase
> to that CTE.
>
> hp
>
>
> --
> _ | Peter J. Holzer | we build much bigger, better disasters now
> |_|_) | | because we have much more sophisticated
> | | | hjp(at)hjp(dot)at | management tools.
> __/ | http://www.hjp.at/ | -- Ross Anderson <https://www.edge.org/>
>

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Begin Daniel 2019-01-27 22:37:53 RE: Error message restarting a database
Previous Message Michel Pelletier 2019-01-27 22:26:04 Re: Implementing an expanded object in C