Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Oracle 19: Find ID of a filtered subset of rows based on the maximum value of a third column

Given a "summary" table with 4 or more columns:

(ID1, ID2, SortOrder, BooleanYN1, BooleanYN2)

For each value of ID1, I want the value of ID2 that corresponds to the row with BooleanYN{n} = Y that has the highest value of SortOrder, if any such records exist.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Example:

ID1 ID2 SortOrder BooleanYN1 BooleanYN2
1 10 1 Y N
1 20 2 N N
1 30 3 Y N
1 40 4 N N

I’m looking for (1, 30, NULL), since the "most recent" (based on SortOrder) row for ID1 = 1 that has BooleanYN1 = 'Y' is the row with ID2 = 30, and there are no rows where BooleanYN2 = 'Y'.

I built a SQL Fiddle with example data here:

http://sqlfiddle.com/#!4/a5bc5/6

This query doesn’t work in the Fiddle because Oracle 11g doesn’t support OUTER APPLY, but it works in Oracle 19.

SELECT
  p.person_id,
  mmr.appointment_id,
  flu.appointment_id,
  covid.appointment_id,
  hiv.appointment_id
FROM
  person p
  OUTER APPLY (
    SELECT vs.appointment_id
      FROM vaccination_summary vs
     WHERE vs.person_id = p.person_id
       AND mmr_yn = 'Y'
     ORDER BY vs.appointment_date DESC
     FETCH FIRST ROW ONLY
  ) mmr
  OUTER APPLY (
    SELECT vs.appointment_id
      FROM vaccination_summary vs
     WHERE vs.person_id = p.person_id
       AND flu_yn = 'Y'
     ORDER BY vs.appointment_date DESC
     FETCH FIRST ROW ONLY
  ) flu
  OUTER APPLY (
    SELECT vs.appointment_id
      FROM vaccination_summary vs
     WHERE vs.person_id = p.person_id
       AND covid_yn = 'Y'
     ORDER BY vs.appointment_date DESC
     FETCH FIRST ROW ONLY
  ) covid
  OUTER APPLY (
    SELECT vs.appointment_id
      FROM vaccination_summary vs
     WHERE vs.person_id = p.person_id
       AND hiv_yn = 'Y'
     ORDER BY vs.appointment_date DESC
     FETCH FIRST ROW ONLY
  ) hiv;

It seems SUPER inelegant and inefficient.

Surely there must be a better way to do this with window functions…or maybe un-pivoting and then re-pivoting?

>Solution :

This sounds like a good candidate for the keep dense_rank aggregate function, e.g. for your example in the sqlfiddle:

SELECT p.person_id,
       p.person_name,
       max(case when mmr_yn = 'Y' then appointment_id end) keep (dense_rank first order by case when mmr_yn = 'Y' then appointment_date end desc nulls last) latest_mmr_vaccine_appt_id,
       max(case when flu_yn = 'Y' then appointment_id end) keep (dense_rank first order by case when flu_yn = 'Y' then appointment_date end desc nulls last) latest_flu_vaccine_appt_id,
       max(case when covid_yn = 'Y' then appointment_id end) keep (dense_rank first order by case when covid_yn = 'Y' then appointment_date end desc nulls last) latest_covid_vaccine_appt_id,
       max(case when hiv_yn = 'Y' then appointment_id end) keep (dense_rank first order by case when hiv_yn = 'Y' then appointment_date end desc nulls last) latest_hiv_vaccine_appt_id
  FROM person p
  JOIN vaccination_summary vs
    ON vs.person_id = p.person_id
 group by p.person_id, p.person_name
 ORDER BY p.person_id;

See the sqlfiddle for the results.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading