2017-04-16 9 views
2

グループ(GRP_ID)の値(ID)を持つ単純なテーブルがあります。グループごとに他の行の最大値を見つける

create table tst as 
select 1 grp_id, 1 id from dual union all 
select 1 grp_id, 1 id from dual union all 
select 1 grp_id, 2 id from dual union all 
select 2 grp_id, 1 id from dual union all 
select 2 grp_id, 2 id from dual union all 
select 2 grp_id, 2 id from dual union all 
select 3 grp_id, 3 id from dual; 

分析関数を使用してグループごとに最大値を見つけるのは簡単です。

select grp_id, id, 
max(id) over (partition by grp_id) max_grp 
from tst 
order by 1,2; 

    GRP_ID   ID MAX_GRP 
---------- ---------- ---------- 
     1   1   2 
     1   1   2 
     1   2   2 
     2   1   2 
     2   2   2 
     2   2   2 
     3   3   3 

しかし、目標は、現在の行の値を除いた最大値を見つけることです。 = 2 GRP_IDにMAX値にタイが存在するので、MAX_OTHER_IDは同じままであること

GRP_ID   ID MAX_GRP MAX_OTHER_ID 
---------- ---------- ---------- ------------ 
     1   1   2   2 
     1   1   2   2 
     1   2   2   1 
     2   1   2   2 
     2   2   2   2 
     2   2   2   2 
     3   3   3    

これは予想される結果(カラムMAX_OTHER_ID)です。

私はこの2つのステップの解決策を管理しましたが、もっと簡単で簡単な解決方法があるのだろうかと思います。

with max1 as (
select grp_id, id, 
row_number() over (partition by grp_id order by id desc) rn 
from tst 
) 
select GRP_ID, ID, 
case when rn = 1 /* MAX row per group */ then 
    max(decode(rn,1,to_number(null),id)) over (partition by grp_id) 
else 
    max(id) over (partition by grp_id) 
end as max_other_id 
from max1 
order by 1,2 

;

max(id) over (
     partition by grp_id 
     order by id 
     range between unbounded preceding and 1 preceding 
     or range between 1 following and unbounded following 
     ) 

しかし残念ながらそうではない。

答えて

4

私はウィンドウ関数は次のように複数の範囲指定のものをサポートしたいです。

回避策として、サブクエリとCTEが異なる範囲でこの関数を2回使用しないようにして、​​3210を呼び出すことができます。合体が原因ウィンドウ関数呼び出しの結果として、発注句の箱から出して動作します

select grp_id, 
    id, 
    coalesce(
      max(id) over (
       partition by grp_id 
       order by id 
       range between 1 following and unbounded following 
       ) 
      , max(id) over (
       partition by grp_id 
       order by id 
       range between unbounded preceding and 1 preceding 
       ) 
      ) max_grp 
from tst 
order by 1, 
    2 

は、与えられたウィンドウ内の最大またはNULL値のいずれかになります。

デモ - http://rextester.com/SDXVF13962

+1

完璧なソリューション。私はしばらくそれに固執していたし、それはOPには単一のクエリで行うことはできないと伝えようとしていた。それはそうです。あなたはいつも新しいことを学びます。 – Utsav

+0

肯定的な 'ID'のための良い解決策。 –

+0

@MarmiteBomber - 私はそれを仮定しました。 – GurV

1
SELECT GRP_ID,ID, (SELECT Max(ID) FROM TEST A WHERE A.ROWID<>B.ROWID AND A.GRP_ID=B.GRP_ID) maX_ID FROM TEST B; 

は、Co-関連のクエリで期待される結果を手に入れました!お役に立てれば 。

関連する問題