Here are sample data
create table VET as select rownum+1 Visit_Id, mod(rownum+1,5) Animal_id, cast(NULL as number) Veterinarian_id, trunc(10*dbms_random.value)+1 Sickness_code from dual connect by level <=100;
Inquiry
basically subqueries do the following:
cumulative and influenza counts (in all animal reports)
calculate RANK (if you only need 3 records, use ROW_NUMBER - see discussion below)
Top of the filter page 3 RANKs
Result LISTAGGregate
with agg as ( select Animal_id, Sickness_code, count(*) cnt, sum(case when SICKNESS_CODE = 5 then 1 else 0 end) over (partition by animal_id) as cnt_flu from vet group by Animal_id, Sickness_code ), agg2 as ( select ANIMAL_ID, SICKNESS_CODE, CNT, cnt_flu, rank() OVER (PARTITION BY ANIMAL_ID ORDER BY cnt DESC) rnk from agg ), agg3 as ( select ANIMAL_ID, SICKNESS_CODE, CNT, CNT_FLU, RNK from agg2 where rnk <= 3 ) select ANIMAL_ID, max(CNT_FLU) CNT_FLU, LISTAGG(SICKNESS_CODE||'('||CNT||')', ', ') WITHIN GROUP (ORDER BY rnk) as cnt_lts from agg3 group by ANIMAL_ID order by 1;
gives
ANIMAL_ID CNT_FLU CNT_LTS ---------- ---------- --------------------------------------------- 0 1 6(5), 1(4), 9(3) 1 1 1(5), 3(4), 2(3), 8(3) 2 0 1(5), 10(3), 4(3), 6(3), 7(3) 3 1 5(4), 2(3), 4(3), 7(3) 4 1 2(5), 10(4), 1(2), 3(2), 5(2), 7(2), 8(2)
I intentionally show Sickness_code (hit count) to demonstrate that top 3 can have links that you need to handle. Check the RANK function. Using ROW_NUMBER in this case is not deterministic.