问题
I am trying to fetch every 15min data in such a way that, if the current time is 23-10-19 11:11:30 then I need to get the data from 23-10-19 10:30:59 to 23-10-19 10:45:59 in the same way if the time is 23-10-19 11:15:30 then I need to get the data from 23-10-19 10:45:59 to 23-10-19 11:00:59.
I have tried forgetting the 15min delay but not the way I want to approach. Please suggest me how can we approach the scenario
select concat(to_char(current_timestamp - numtodsinterval(30,'MINUTE'),'yyyy-mm-dd hh24:mi'),':59') A,
concat(to_char(current_timestamp - numtodsinterval(15,'MINUTE'),'yyyy-mm-dd hh24:mi'),':59') B,
to_char(current_timestamp,'yyyy-mm-dd hh24:mi:ss') C from dual
below is the output that I was getting.
A B C
------------------- ------------------- -------------------
2019-10-23 13:03:59 2019-10-23 13:18:59 2019-10-23 13:33:22
回答1:
You can truncate to the nearest minute to zero the seconds and then subtract the number of minutes to get back to the nearest 15 minute interval past the hour and then apply your offsets:
SELECT TRUNC( current_timestamp, 'MI' )
- MOD( EXTRACT( MINUTE FROM current_timestamp ), 15 ) * INTERVAL '1' MINUTE
- INTERVAL '30' MINUTE
+ INTERVAL '59' SECOND AS start_time,
TRUNC( current_timestamp, 'MI' )
- MOD( EXTRACT( MINUTE FROM current_timestamp ), 15 ) * INTERVAL '1' MINUTE
- INTERVAL '15' MINUTE
+ INTERVAL '59' SECOND AS end_time,
current_timestamp
FROM DUAL
Outputs:
START_TIME | END_TIME | CURRENT_TIMESTAMP :------------------ | :------------------ | :---------------------------- 2019-10-23 09:00:59 | 2019-10-23 09:15:59 | 2019-10-23 09:42:53.742684000
db<>fiddle here
回答2:
Another solution is this one:
WITH t AS
(SELECT TRUNC(CURRENT_TIMESTAMP , 'hh') + TRUNC(EXTRACT(MINUTE FROM CURRENT_TIMESTAMP ) / 15) * INTERVAL '15' MINUTE - INTERVAL '30' MINUTE AS Base
FROM dual)
SELECT Base + INTERVAL '59' SECOND AS begin_time,
Base + INTERVAL '15:59' minute to SECOND AS end_time
FROM t;
It is based on my generic Interval function:
CREATE OR REPLACE FUNCTION MakeInterval(ts IN TIMESTAMP, roundInterval IN INTERVAL DAY TO SECOND) RETURN TIMESTAMP DETERMINISTIC IS
denom INTEGER;
BEGIN
IF roundInterval >= INTERVAL '1' HOUR THEN
denom := EXTRACT(HOUR FROM roundInterval);
IF MOD(24, denom) <> 0 THEN
RAISE VALUE_ERROR;
END IF;
RETURN TRUNC(ts) + TRUNC(EXTRACT(HOUR FROM ts) / denom) * denom * INTERVAL '1' HOUR;
ELSIF roundInterval >= INTERVAL '1' MINUTE THEN
denom := EXTRACT(MINUTE FROM roundInterval);
IF MOD(60, denom) <> 0 THEN
RAISE VALUE_ERROR;
END IF;
RETURN TRUNC(ts, 'hh') + TRUNC(EXTRACT(MINUTE FROM ts) / denom) * denom * INTERVAL '1' MINUTE;
ELSE
denom := EXTRACT(SECOND FROM roundInterval);
IF MOD(60, denom) <> 0 THEN
RAISE VALUE_ERROR;
END IF;
RETURN TRUNC(ts, 'mi') + TRUNC(EXTRACT(SECOND FROM ts) / denom) * denom * INTERVAL '1' SECOND;
END IF;
END MakeInterval;
You would invoke it as
SELECT MakeInterval(CURRENT_TIMESTAMP, INTERVAL '15' MINUTE) from dual;
plus/minus your constant offsets.
回答3:
select :start_date + (1/96)*(level-1) from dual connect by level < :intervals
来源:https://stackoverflow.com/questions/58518246/how-can-we-get-the-15-minutes-time-interval