Reputation: 8905
I would like to get per N the max(date) <= sysdate. If no dates in the past/today exist I want the min(date). So I do not want the absolute date nearest to sysdate.
Testdata
CREATE TABLE DATTEST (N NUMBER, D DATE);
INSERT INTO DATTEST (N,D) VALUES (1,TRUNC(SYSDATE-2000));
INSERT INTO DATTEST (N,D) VALUES (1,TRUNC(SYSDATE-1000));
INSERT INTO DATTEST (N,D) VALUES (1,TRUNC(SYSDATE+100));
INSERT INTO DATTEST (N,D)VALUES (2,TRUNC(SYSDATE));
INSERT INTO DATTEST (N,D)VALUES (2,TRUNC(SYSDATE+1000));
INSERT INTO DATTEST (N,D)VALUES (3,TRUNC(SYSDATE+1000));
So far I've got this. It gives the right results bus does two tablescans. I'm working on large tables and this query is called many times. I've been breaking my head converting this to a single table scan.
with nums as
(SELECT LEVEL num
FROM DUAL
CONNECT BY LEVEL <= 3
)
select
num
,(nvl((select max(d)
from dattest
where d <= trunc(sysdate)
and n = num),
(select min(d)
from dattest
where d > trunc(sysdate)
and n = num))
)
from nums;
Expected output
1 26-06-12
2 23-03-15
3 17-12-17
Upvotes: 1
Views: 1014
Reputation: 1269483
How about using an aggregation, with some conditional logic?
select id,
coalesce(max(case when d <= trunc(sysdate) then d end),
min(d)
)
from table t
group by id;
Upvotes: 2