I try to understand LATERAL JOIN with this query:
select m1.contributor_prescription, derniere_publication.date_publication_prescription
from activite.metadonnee m1
left join lateral
(select date_publication_prescription, m2.contributor_prescription
from activite.metadonnee m2
where m1.contributor_prescription = m2.contributor_prescription
order by date_publication_prescription desc
limit 3) as derniere_publication
ON true
order by m1.contributor_prescription
The goal is to have for each contributor_prescription the 3 latest date_publication_prescription.
For now, the result is all contributor_prescription rows and the last date_publication_prescription for all.
| contributor_prescription | date_publication_prescription |
|---|---|
| john | 22/10/2023 |
| john | 22/10/2023 |
| (as many times as john exists in the table) | |
| paul | 24/10/2023 |
| paul | 24/10/2023 |
| (as many times as paul exists in the table) |
expected:
| contributor_prescription | date_publication_prescription |
|---|---|
| john | 22/10/2023 |
| john | 21/10/2023 |
| john | 20/10/2023 |
| paul | 24/10/2023 |
| paul | 23/10/2023 |
| paul | 21/10/2023 |
If you want the top 3 most recent per
contributor_prescriptionyou can order them withrow_number(), then keep only the top 3 using a plainwhere: demoOr you could do what you did, but don't join straight to the source table, but to
distinct contributor_prescription:Otherwise you're asking every single row to show you 3 most recent rows with the same
contributor_prescription, needlessly multiplying everything. Note the performance of that isn't great.There's also a very brief method of collecting into an array, taking a slice and unnesting that:
But the most performant would be the infamous (still emulated) index skip scan: demo