Обсуждение: Extract only maximum date from column

Поиск
Список
Период
Сортировка

Extract only maximum date from column

От
Rich Shepard
Дата:
I want the script to extract only the maximum `next_contact' date and
haven't learned how to do this from my reading of web sites.

The script:

select p.person_nbr, p.company_nbr, c.next_contact
from people as p, contacts as c
where c.next_contact >= '2025-11-01'
group by p.person_nbr, p.company_nbr, c.next_contact
order by p.person_nbr, p.company_nbr, max(c.next_contact);

returns all contacts rather than only the latest one.

Is using a sub-select the proper way?

TIA,

Rich



Re: Extract only maximum date from column

От
Bryan Sayer
Дата:

I believe in general you need

having c.next_contact = max(c.next_contact)

(at least in ANSI SQL) Use having for after the join has occured

Bryan Sayer
Retired Demographer/Statistician
In a world in which you can be anything, be kind
On 12/4/2025 2:55 PM, Rich Shepard wrote:
I want the script to extract only the maximum `next_contact' date and
haven't learned how to do this from my reading of web sites.

The script:

select p.person_nbr, p.company_nbr, c.next_contact
from people as p, contacts as c
where c.next_contact >= '2025-11-01'
group by p.person_nbr, p.company_nbr, c.next_contact
order by p.person_nbr, p.company_nbr, max(c.next_contact);

returns all contacts rather than only the latest one.

Is using a sub-select the proper way?

TIA,

Rich


Re: Extract only maximum date from column

От
Ron Johnson
Дата:
On Thu, Dec 4, 2025 at 2:55 PM Rich Shepard <rshepard@appl-ecosys.com> wrote:
I want the script to extract only the maximum `next_contact' date and
haven't learned how to do this from my reading of web sites.

The script:

select p.person_nbr, p.company_nbr, c.next_contact
from people as p, contacts as c
where c.next_contact >= '2025-11-01'
group by p.person_nbr, p.company_nbr, c.next_contact
order by p.person_nbr, p.company_nbr, max(c.next_contact);

returns all contacts rather than only the latest one.

Is using a sub-select the proper way?

May not be the only way, but it's how I do it:
SELECT * 
FROM foo
WHERE some_dt = (SELECT MAX(some_dt) FROM foo);

It might return more than one row...

--
Death to <Redacted>, and butter sauce.
Don't boil me, I'm still alive.
<Redacted> lobster!

Re: Extract only maximum date from column

От
"David G. Johnston"
Дата:
On Thursday, December 4, 2025, Rich Shepard <rshepard@appl-ecosys.com> wrote:
I want the script to extract only the maximum `next_contact' date and
haven't learned how to do this from my reading of web sites.

The script:

select p.person_nbr, p.company_nbr, c.next_contact
from people as p, contacts as c
where c.next_contact >= '2025-11-01'
group by p.person_nbr, p.company_nbr, c.next_contact
order by p.person_nbr, p.company_nbr, max(c.next_contact);

returns all contacts rather than only the latest one.

Is using a sub-select the proper way?

I would go with a lateral join subquery of the contracts table.  Using an aggregates to perform ranking is an anti-pattern. You want the contract ranked first when ordered by contract_date.  Either use a window function to explicitly rank the contracts or use a limit/fetch clause to simply return the first ordered one.

You also seem to have completely missed joining people to contracts - suggest using explicit “join” clauses to make that error less likely.

David J.

Re: Extract only maximum date from column

От
Rich Shepard
Дата:
On Thu, 4 Dec 2025, Bryan Sayer wrote:

> I believe in general you need
>
> having c.next_contact = max(c.next_contact)
>
> (at least in ANSI SQL) Use having for after the join has occurred

Bryan,

Postgresql didn't like that regardless of where I inserted the `having'
stanza.

Thanks,

Rich



Re: Extract only maximum date from column

От
Rich Shepard
Дата:
On Thu, 4 Dec 2025, Ron Johnson wrote:

> May not be the only way, but it's how I do it:
> SELECT *
> FROM foo
> WHERE some_dt = (SELECT MAX(some_dt) FROM foo);
>
> It might return more than one row...

Ron,

Didn't quite work for me this way:

select p.person_nbr, p.company_nbr, c.next_contact
from people as p, contacts as c
where c.next_contact (select max(c.next_contact) from c.contacts) >= '2025-11-01'
group by p.person_nbr, p.company_nbr
order by p.person_nbr, p.company_nbr;

Thanks,

Rich



Re: Extract only maximum date from column

От
Rich Shepard
Дата:
On Thu, 4 Dec 2025, David G. Johnston wrote:

> I would go with a lateral join subquery of the contracts table. Using an
> aggregates to perform ranking is an anti-pattern. You want the contract
> ranked first when ordered by contract_date. Either use a window function
> to explicitly rank the contracts or use a limit/fetch clause to simply
> return the first ordered one.

David,

It's 'contacts' rather than 'contracts'; a minor typo.

I'll read on making a lateral join. Thanks.

> You also seem to have completely missed joining people to contracts -
> suggest using explicit “join” clauses to make that error less likely.

Oops! My bad. Fixed.

Regards,

Rich



Re: Extract only maximum date from column

От
Bryan Sayer
Дата:

You don't include the where clause, just the having clause after the group by.

At least that is what I remember. But it has been awhile.

Bryan Sayer
Retired Demographer/Statistician
In a world in which you can be anything, be kind
On 12/4/2025 3:13 PM, Rich Shepard wrote:
On Thu, 4 Dec 2025, Bryan Sayer wrote:

I believe in general you need

having c.next_contact = max(c.next_contact)

(at least in ANSI SQL) Use having for after the join has occurred

Bryan,

Postgresql didn't like that regardless of where I inserted the `having'
stanza.

Thanks,

Rich


Re: Extract only maximum date from column

От
Rich Shepard
Дата:
On Thu, 4 Dec 2025, David G. Johnston wrote:

> I would go with a lateral join subquery of the contracts table. Using an
> aggregates to perform ranking is an anti-pattern. You want the contract
> ranked first when ordered by contract_date. Either use a window function
> to explicitly rank the contracts or use a limit/fetch clause to simply
> return the first ordered one.

David,

I'm closer, but still missing the proper syntax:

select p.person_nbr, p.company_nbr, c.next_contact
from people as p, contacts as c
join lateral (select max(c.next_contact) as last_contact
      where p.person_nbr = c.person_nbr and
      last_contact >= '2025-11-01'
      )
      c on true;

resulting in:
psql:companies-contacted-2025.sql:9: ERROR:  aggregate functions are not allowed in FROM clause of their own query
level
LINE 3: join lateral (select max(c.next_contact) as last_contact

Regards,

Rich



Re: Extract only maximum date from column

От
Adrian Klaver
Дата:

On 12/4/25 1:39 PM, Rich Shepard wrote:
> On Thu, 4 Dec 2025, David G. Johnston wrote:
> 
>> I would go with a lateral join subquery of the contracts table. Using an
>> aggregates to perform ranking is an anti-pattern. You want the contract
>> ranked first when ordered by contract_date. Either use a window function
>> to explicitly rank the contracts or use a limit/fetch clause to simply
>> return the first ordered one.
> 
> David,
> 
> I'm closer, but still missing the proper syntax:
> 
> select p.person_nbr, p.company_nbr, c.next_contact
> from people as p, contacts as c
> join lateral (select max(c.next_contact) as last_contact
>       where p.person_nbr = c.person_nbr and
>       last_contact >= '2025-11-01'
>       )
>       c on true;
> 
> resulting in:
> psql:companies-contacted-2025.sql:9: ERROR:  aggregate functions are not 
> allowed in FROM clause of their own query level
> LINE 3: join lateral (select max(c.next_contact) as last_contact

Would the below work?:

WITH lc AS (SELECT person_nbr, max(next_contact) AS last_contact from 
contacts where next_contact > '2025-11-01' group by c.person_nbr)
select p.person_nbr, p.company_nbr, lc.last_contact from people AS p 
join lc on p.person.nbr = lc.person_nbr;

> 
> Regards,
> 
> Rich
> 
> 

-- 
Adrian Klaver
adrian.klaver@aklaver.com




Re: Extract only maximum date from column

От
"David G. Johnston"
Дата:
On Thursday, December 4, 2025, Rich Shepard <rshepard@appl-ecosys.com> wrote:
On Thu, 4 Dec 2025, David G. Johnston wrote:

I would go with a lateral join subquery of the contracts table. Using an
aggregates to perform ranking is an anti-pattern. You want the contract
ranked first when ordered by contract_date. Either use a window function
to explicitly rank the contracts or use a limit/fetch clause to simply
return the first ordered one.

David,

I'm closer, but still missing the proper syntax:

select p.person_nbr, p.company_nbr, c.next_contact
from people as p, contacts as c
join lateral (select max(c.next_contact) as last_contact
     where p.person_nbr = c.person_nbr and
     last_contact >= '2025-11-01'
     )
     c on true;

resulting in:
psql:companies-contacted-2025.sql:9: ERROR:  aggregate functions are not allowed in FROM clause of their own query level
LINE 3: join lateral (select max(c.next_contact) as last_contact

As mentioned, the aggregate max should be avoided - you aren’t doing statistics, you are ranking.

Select person.*, lastcontact.* from person join lateral (select contact.* from contact where contact.person_id=person.person_id  order by last_contact_date desc limit 1) as lastcontact on true;

David J.

Re: Extract only maximum date from column

От
Rich Shepard
Дата:
On Thu, 4 Dec 2025, Adrian Klaver wrote:

> Would the below work?:
>
> WITH lc AS (SELECT person_nbr, max(next_contact) AS last_contact from 
> contacts where next_contact > '2025-11-01' group by c.person_nbr)
> select p.person_nbr, p.company_nbr, lc.last_contact from people AS p join lc 
> on p.person.nbr = lc.person_nbr;

Adrian,

Reformated and still has an error:
WITH lc AS (SELECT person_nbr, max(next_contact) AS last_contact
      from contacts where next_contact >= '2025-11-01'
      group by c.person_nbr)
select p.person_nbr, p.company_nbr, lc.last_contact
from people AS p
join lc on p.person.nbr = lc.person_nbr;

psql:companies-contacted-2025.sql:16: ERROR:  missing FROM-clause entry for table "c"
LINE 3:      group by c.person_nbr)

So, tweaking from reported errors:
WITH lc AS (SELECT p.person_nbr, max(c.next_contact) AS last_contact
      from people as p, contacts as c
      where next_contact >= '2025-11-01'
      group by p.person_nbr)
select p.person_nbr, p.company_nbr, lc.last_contact
from people AS p
join lc on p.person.nbr = lc.person_nbr;

psql:companies-contacted-2025.sql:9: ERROR:  missing FROM-clause entry for table "person"
LINE 7: join lc on p.person.nbr = lc.person_nbr;
                    ^
This is obviously a much more complicated query than I expected.

Thanks,

Rich



Re: Extract only maximum date from column

От
Rich Shepard
Дата:
On Thu, 4 Dec 2025, David G. Johnston wrote:

> As mentioned, the aggregate max should be avoided - you aren’t doing
> statistics, you are ranking.

David,

Got it.

> Select person.*, lastcontact.* from person join lateral (select contact.*
> from contact where contact.person_id=person.person_id order by
> last_contact_date desc limit 1) as lastcontact on true;

Select person.*, lastcontact.*
from people
join lateral (select contact.*
      from contacts
      where contacts.person_nbr = people.person_nbr
      order by last_contact_date
      desc limit 1)
as lastcontact on true;

psql:companies-contacted-2025.sql:10: ERROR:  missing FROM-clause entry for table "contact"
LINE 3: join lateral (select contact.*

So:
Select person.*, lastcontact.*
from people
join lateral (select contacts.*
      from contacts
      where contacts.person_nbr = people.person_nbr
      order by last_contact_date
      desc limit 1)
as lastcontact on true;

psql:companies-contacted-2025.sql:10: ERROR:  column "last_contact_date" does not exist
LINE 6:      order by last_contact_date
                       ^
Regards,

Rich



Re: Extract only maximum date from column

От
"David G. Johnston"
Дата:
On Thursday, December 4, 2025, Rich Shepard <rshepard@appl-ecosys.com> wrote:
On Thu, 4 Dec 2025, David G. Johnston wrote:

As mentioned, the aggregate max should be avoided - you aren’t doing
statistics, you are ranking.

David,

Got it.

Select person.*, lastcontact.* from person join lateral (select contact.*
from contact where contact.person_id=person.person_id order by
last_contact_date desc limit 1) as lastcontact on true;

Select person.*, lastcontact.*
from people
join lateral (select contact.*
     from contacts
     where contacts.person_nbr = people.person_nbr
     order by last_contact_date
     desc limit 1)
as lastcontact on true;

psql:companies-contacted-2025.sql:10: ERROR:  missing FROM-clause entry for table "contact"
LINE 3: join lateral (select contact.*

So:
Select person.*, lastcontact.*
from people
join lateral (select contacts.*
     from contacts
     where contacts.person_nbr = people.person_nbr
     order by last_contact_date
     desc limit 1)
as lastcontact on true;

psql:companies-contacted-2025.sql:10: ERROR:  column "last_contact_date" does not exist
LINE 6:      order by last_contact_date
                       

I was giving you a query form.  You should use the actual table and column names in your schema…

David J.
 

Re: Extract only maximum date from column

От
Adrian Klaver
Дата:
On 12/4/25 14:17, Rich Shepard wrote:
> On Thu, 4 Dec 2025, Adrian Klaver wrote:
> 

> So, tweaking from reported errors:
> WITH lc AS (SELECT p.person_nbr, max(c.next_contact) AS last_contact
>       from people as p, contacts as c
>       where next_contact >= '2025-11-01'
>       group by p.person_nbr)
> select p.person_nbr, p.company_nbr, lc.last_contact
> from people AS p
> join lc on p.person.nbr = lc.person_nbr;
> 
> psql:companies-contacted-2025.sql:9: ERROR:  missing FROM-clause entry 
> for table "person"
> LINE 7: join lc on p.person.nbr = lc.person_nbr;

My mistake should be p.person_nbr

>                     ^
> This is obviously a much more complicated query than I expected.
> 
> Thanks,
> 
> Rich
> 
> 


-- 
Adrian Klaver
adrian.klaver@aklaver.com



Re: Extract only maximum date from column

От
Alban Hertroys
Дата:
> On 4 Dec 2025, at 20:55, Rich Shepard <rshepard@appl-ecosys.com> wrote:
>
> I want the script to extract only the maximum `next_contact' date and
> haven't learned how to do this from my reading of web sites.
>
> The script:
>
> select p.person_nbr, p.company_nbr, c.next_contact
> from people as p, contacts as c
> where c.next_contact >= '2025-11-01'
> group by p.person_nbr, p.company_nbr, c.next_contact
> order by p.person_nbr, p.company_nbr, max(c.next_contact);
>
> returns all contacts rather than only the latest one.
>
> Is using a sub-select the proper way?
>
> TIA,
>
> Rich

That looks like a classical case for a correlated subquery with WHERE NOT EXISTS.

Something like:

select p.person_nbr, p.company_nbr, c.next_contact
from people as p
join contacts as c
on -- I’m really missing some kind of relation between p and c here, I think that’s relevant
where c.next_contact >= ‘2025-11-01’
-- make sure there’s no later contact
and not exists (
    select 1 -- the value is irrelevant, as long as there’s no later instance of a contact
    from contacts c2
    where c2.next_contact >= ‘2025-11-01’
    and c2.next_contact > c.next_contact
)

P.S. My mail-client tried to outsmart me in this reply (in no small part) and I just got back from the pub, so I can’t
exactlyguarantee correctness of the above, but the principal idea should be solid. 

Alban Hertroys
--
There is always an exception to always.