sql >> データベース >  >> RDS >> Oracle

Oracle ListaGG、IDでグループ化された1つの列に示される上位3つの最も頻度の高い値

    ここにサンプルデータ

    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;
    

    クエリ

    基本的に、サブクエリは次のことを行います。

    インフルエンザの数を集計して計算します(動物のすべての記録で)

    RANKを計算します(実際に3つのレコードのみが必要な場合はROW_NUMBERを使用します-以下の説明を参照してください)

    上位3つのランクをフィルタリングする

    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;
    

    与える

     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) 
    

    意図的にSickness_code(count visits)を表示して、上位3つが処理する必要のあるタイを持つ可能性があることを示します。RANK関数を確認してください。 ROW_NUMBERの使用 この場合、決定論的ではありません。



    1. ローリング日付範囲内の個別の値の数を照会します

    2. ORA-00955の回避:nameは既存のオブジェクトによってすでに使用されています

    3. MYSQLのサブクエリでLIMITキーワードを使用する代わりに

    4. Javaでデータベースリスナーを作成するにはどうすればよいですか?