查找每组其他行的最大值
Find Maximal Value of other Rows per Group
我有一个简单的 table,其中值 (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
;
我希望 window 函数支持多个范围规范,例如:
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 在不同范围内两次使用该函数,并在其上调用 coalesce
。
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
Coalesce 开箱即用,因为排序子句作为 window 函数调用的结果将是给定 window 中的最大值或空值。
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-Related Query 获得了预期的结果!希望这有帮助。
我有一个简单的 table,其中值 (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
;
我希望 window 函数支持多个范围规范,例如:
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 在不同范围内两次使用该函数,并在其上调用 coalesce
。
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
Coalesce 开箱即用,因为排序子句作为 window 函数调用的结果将是给定 window 中的最大值或空值。
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-Related Query 获得了预期的结果!希望这有帮助。