2017-04-16 76 views
2

我有一组简单的表(ID)(GRP_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 

但目标是找到排除当前行的值的最大值。

这是预期的结果(柱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    

注意,在GRP_ID = 2上的MAX值存在平局,所以MAX_OTHER_ID保持相同。

我确实管理了这个两步骤的解决方案,但我想知道是否有更直接简单的解决方案。

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 

;

回答

4

祝窗口功能支持多个规格品种齐全是这样的:

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 
     ) 

但不幸的是他们不这样做。

作为一种解决方法,您可以避免子查询和CTE在不同范围上使用该函数两次,并在该范围上调用​​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 

合并开箱,因为排序子句作为窗口函数调用的结果将是无论是在给定的窗口的最大或空值。

演示 - 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; 

得到了与合作相关的查询期望的结果!希望这可以帮助 。