I have a table WT_RT.
a select
on it will give me this result
select * from WT_RT;
WT_SEQ W RT_AMT R
---------- - ---------- -
0 0 125 M
1 2 9.3 N
45 2 7.19 Q
100 1 6.38 Q
300 1 5.11 Q
500 2 4.69 Q
1000 2 4.39 Q
On input of WT_SEQ=250
, since 250 is in between 100 and 300 I need to select the row which has the least RT_AMT
. In this case, since 5.11 < 6.38
, I need to select the row with WT_SEQ
= 300.
Expected Result:
WT_SEQ W RT_AMT R
---------- - ---------- -
300 1 5.11 Q
So far I have managed to find the enclosing 2 rows.
select ........;
WT_SEQ W RT_AMT R
---------- - ---------- -
100 1 6.38 Q
300 1 5.11 Q
But I need to implement the condition of minimum value of RT_AMT
How to do it?
One way is via a top 2 of an order by distance.
Then the top 1 of an order by RT_AMT.
select WT_SEQ, RT_AMT
from
(
select *
from
(
select *
from WT_RT
cross join (select 250 val from dual) v
order by ABS(WT_SEQ - val)
) q1
where rownum <= 2
order by (case when WT_SEQ = val then 1 else 2 end), RT_AMT asc
) q2
where rownum = 1;
The CASE WHEN is added to give priority to an WT_SEQ that's equal to the value.
You can try to write a subquery to get nextval by LEAD
then, use BETWEEN
to get between WT_SEQ
column, then self join
by WT_SEQ
then use Row_NUMBER
with Windows Function to make Rownumber by RT_AMT
, then get rn = 1
TestDLL
CREATE TABLE WT_RT(
WT_SEQ INT,
RT_AMT FLOAT
);
INSERT INTO WT_RT VALUES (0,125);
INSERT INTO WT_RT VALUES ( 1, 9.3);
INSERT INTO WT_RT VALUES ( 45,7.19);
INSERT INTO WT_RT VALUES ( 100,6.38);
INSERT INTO WT_RT VALUES ( 300,5.11);
INSERT INTO WT_RT VALUES ( 500,4.69);
INSERT INTO WT_RT VALUES (1000,4.39);
Query
WITH CTE1 AS(
SELECT t2.WT_SEQ,t2.RT_AMT,Row_NUMBER() OVER(ORDER BY t2.RT_AMT) rn
FROM (
SELECT * FROM (
SELECT t1.*,LEAD(WT_SEQ,1,WT_SEQ) over(order by WT_SEQ) nextval
FROM WT_RT t1
)t1
WHERE 250 BETWEEN WT_SEQ and nextval
) t1 INNER JOIN WT_RT t2
on t1.WT_SEQ = t2.WT_SEQ or t1.NEXTVAL = t2.WT_SEQ
)
SELECT *
FROM CTE1
WHERE RN = 1
[Results] :
| WT_SEQ | RT_AMT | RN |
|--------|--------|----|
| 300 | 5.11 | 1 |
You can just use aggregation:
select MIN(RT_AMT)
from WT_RT
where WT_SEQ <= 250
If you need the entire row, you can select one row. In Oracle 12C+:
select MIN(RT_AMT)
from WT_RT
where WT_SEQ <= 250
order by WT_SEQ desc
fetch first 1 row only;
In older version:
select x.*
from (select MIN(RT_AMT)
from WT_RT
where WT_SEQ <= 250
order by WT_SEQ desc
) x
where rownum = 1;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.