Sql 距离每个距离的最大值
我想计算每个可能的距离到最大值的距离。例如:Sql 距离每个距离的最大值,sql,oracle,oracle12c,Sql,Oracle,Oracle12c,我想计算每个可能的距离到最大值的距离。例如: Row Distance Value 1 1 2 --> 1 (Distance from Row 1) 2 2 3 --> 2 (Distance from Row 2) 3 3 3 --> 2 (Distance from Row 2) 4 4 1 --> 2 (Distance from Row 2)
Row Distance Value
1 1 2 --> 1 (Distance from Row 1)
2 2 3 --> 2 (Distance from Row 2)
3 3 3 --> 2 (Distance from Row 2)
4 4 1 --> 2 (Distance from Row 2)
5 5 5 --> 5 (Distance from Row 5)
6 6 1 --> 5 (Distance from Row 5)
说明:第6行的值为5,因为第1行到第6行之间的最大值第一次出现在距离5处
我曾尝试使用一些windows功能,但不知道如何将其组合在一起
样本数据:
--drop table tmp_maxval;
create table tmp_maxval (dst number, val number);
insert into tmp_maxval values(1, 3);
insert into tmp_maxval values(2, 2);
insert into tmp_maxval values(3, 1);
insert into tmp_maxval values(4, 2);
insert into tmp_maxval values(5, 4);
insert into tmp_maxval values(6, 2);
insert into tmp_maxval values(7, 2);
insert into tmp_maxval values(8, 5);
insert into tmp_maxval values(9, 5);
insert into tmp_maxval values(10,1);
commit;
我认为函数在解决这一问题时很有用:
select t.*,
max(val) over(order by dst),
case when val >= max(val) over(order by dst) then 1 else 0 end ,
case when row_number() over(partition by val order by dst) = 1 then 1 else 0 end as first_occurence
from
ap_risk.tmp_maxval t
您可以使用累积最大值获得最大值:
select mv.*, max(mv.value) over (order by mv.distance) as max_value
from ap_risk.tmp_maxval mv;
我想这回答了你的问题。如果需要距离本身:
select mv.*,
min(case when max_value = value then distance end) over (order by distance) as first_distance_at_max_value
from (select mv.*, max(mv.value) over (order by mv.distance) as max_value
from ap_risk.tmp_maxval mv
) mv;
在下列情况下,您可以将
max()
或min()
与大小写结合使用:
select t.*,
min(case when val = mv then dst end) over (partition by mv order by dst) v1,
max(case when val = mv then dst end) over (partition by mv order by dst) v2
from (select t.*, max(val) over (order by dst) mv from tmp_maxval t) t
order by dst
结果:
DST VAL MV V1 V2
---------- ---------- ---------- ---------- ----------
1 3 3 1 1
2 2 3 1 1
3 1 3 1 1
4 2 3 1 1
5 4 4 5 5
6 2 4 5 5
7 2 4 5 5
8 5 5 8 8
9 5 5 8 9
10 1 5 8 9
解释的逻辑和第一次出现的单词建议您需要min()
,但示例中的第三行建议max()
;-)在您提供的数据中,您可以观察第9-10行中的差异。选择你想要的。显然OP想要的是后者,而不是前者。而您(针对后者)的解决方案是不正确的:由于条件val[ue]=max_val[ue]为true,特别是对于第一行,您的查询将为所有输入行输出1。OP发布了创建表和插入,因此您有义务在发布前进行测试。由于这个原因,绝对是一个否决票-没有理由发布错误的答案。我的解决方案和你的解决方案之间的区别在于,在你的方法中,你还必须在外部查询中按mv进行分区(除了按dst排序)。这是一个额外的排序,现在ORDER BY子句导致了第三个排序-您可以在Explain计划中清楚地看到它,并且成本也反映了它:我的查询为4,您的查询为6(在非常小的数据集上)。这就是为什么我创建了这个标志,并在外部查询中使用了与内部查询中完全相同的分析子句的分析函数。话虽如此,您的查询肯定是正确的。
select t.*,
min(case when val = mv then dst end) over (partition by mv order by dst) v1,
max(case when val = mv then dst end) over (partition by mv order by dst) v2
from (select t.*, max(val) over (order by dst) mv from tmp_maxval t) t
order by dst
DST VAL MV V1 V2
---------- ---------- ---------- ---------- ----------
1 3 3 1 1
2 2 3 1 1
3 1 3 1 1
4 2 3 1 1
5 4 4 5 5
6 2 4 5 5
7 2 4 5 5
8 5 5 8 8
9 5 5 8 9
10 1 5 8 9