programing

날짜를 10분 간격으로 반올림

powerit 2023. 7. 7. 21:10
반응형

날짜를 10분 간격으로 반올림

나는 있습니다DATE쿼리에서 다음으로 낮은 10분 간격으로 반올림할 열(아래 예 참조).

저는 몇 초를 잘라내고 마지막 몇 분을 빼면서 그것을 할 수 있었습니다.

WITH test_data AS (
        SELECT TO_DATE('2010-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
  UNION SELECT TO_DATE('2010-01-01 10:05:00', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
  UNION SELECT TO_DATE('2010-01-01 10:09:59', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
  UNION SELECT TO_DATE('2010-01-01 10:10:00', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
  UNION SELECT TO_DATE('2099-01-01 10:00:33', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
)
-- #end of test-data
SELECT
  d, TRUNC(d, 'MI') - MOD(TO_CHAR(d, 'MI'), 10) / (24 * 60)
FROM test_data

그 결과는 다음과 같습니다.

01.01.2010 10:00 01.01.2010 10:00:00
01.01.2010 10:05:00 01.01.2010 10:00:00
01.01.2010 10:09:59 01.01.2010 10:00:00
01.01.2010 10:10 01.01.2010 10:10:00
01.01.2099 10:00:3301.01.2099 10:00

예상대로 작동합니다만, 더 좋은 방법이 있을까요?

편집:

저는 성능에 대해 궁금했기 때문에 다음 테스트를 500,000개의 행과 (사실상) 무작위 날짜로 수행했습니다.저는 제공된 솔루션에 코멘트로 결과를 추가할 것입니다.

DECLARE
  t       TIMESTAMP := SYSTIMESTAMP;
BEGIN
  FOR i IN (
    WITH test_data AS (
      SELECT SYSDATE + ROWNUM / 5000 d FROM dual
      CONNECT BY ROWNUM <= 500000
    )
    SELECT TRUNC(d, 'MI') - MOD(TO_CHAR(d, 'MI'), 10) / (24 * 60)
    FROM test_data
  )
  LOOP
    NULL;
  END LOOP;
  dbms_output.put_line( SYSTIMESTAMP - t );
END;

이 접근 방식은03.24 s.

select
  trunc(sysdate, 'mi')
  - numtodsinterval(mod(EXTRACT(minute FROM cast(sysdate as timestamp)), 10), 'minute')
from dual;

아니 심지어는

select
  trunc(sysdate, 'mi')
  - mod(EXTRACT(minute FROM cast(sysdate as timestamp)), 10) / (24 * 60)
from dual;

저는 일반적으로 데이트 -> 캐릭터 -> 데이트 변환이 필요 없을 때 하는 것을 싫어합니다.숫자를 쓰는 게 낫겠어요.

select trunc((sysdate - trunc(sysdate))*60*24,-1)/(60*24)+trunc(sysdate) from dual;     

이렇게 하면 현재 날짜에서 분을 추출하여 10분 간격으로 잘라낸 다음 다시 추가하여 날짜를 다시 지정합니다.물론 sysdate를 원하는 날짜로 바꿀 수 있습니다.그것은 내가 원하는 것보다 훨씬 더 암묵적인 변환을 신뢰하지만 적어도 어떤 NLS 날짜 형식에서도 작동할 것입니다.

반환된 값을 문자열로 사용하고 왼쪽을 마지막 1분 자리까지 하위 문자열로 대체할 수 있습니다.0당신이 어떤 종류의 지표를 제공하지 않는 한 저는 그것을 정확히 더 잘 말하지 않을 것입니다.

반드시 더 나은 것은 아니지만, 다른 방법:

WITH test_data AS (
        SELECT TO_DATE('2010-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
  UNION SELECT TO_DATE('2010-01-01 10:05:00', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
  UNION SELECT TO_DATE('2010-01-01 10:09:59', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
  UNION SELECT TO_DATE('2010-01-01 10:10:00', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
  UNION SELECT TO_DATE('2099-01-01 10:00:33', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
)
-- #end of test-data
SELECT
  d, TRUNC(d) + FLOOR((d-TRUNC(d))*24*6)/(24*6)
FROM test_data

또 다른 방법은,

select my_date - mod( (my_date-trunc(my_date))*24*60, 10)/24/60
from (
  select sysdate my_date from dual
);

잘라내기 호출을 제거하기 때문에 더 빠를 수도 있습니다.

select my_date - mod( (my_date-to_date('1970', 'yyyy'))*24*60, 10)/24/60
from (
  select sysdate my_date from dual
);

다음 상위 10분 간격을 반환하기 위해 다음 쿼리를 사용했습니다.단순히 할 수 없었기 때문에 유용하게 쓰였으면 좋겠습니다.

trunc(sysdate, 'mi') + mod(EXTRACT(minute FROM cast(sysdate as timestamp)), 10) / (24 * 60)

저는 이것을 했고 그것은 저에게 효과가 있었습니다.

select 
case when mod(EXTRACT(minute FROM cast(sysdate as timestamp)),5) between 1 and 4
      then trunc(sysdate,'mi')+((5*TRUNC(EXTRACT(minute FROM cast(sysdate as timestamp))/5,
0)+5)-EXTRACT(minute FROM cast(sysdate as timestamp)))/1440
      else trunc(sysdate,'mi')
end
from dual

이것은 이 게시물을 기반으로 합니다.

이 문제를 해결하려면 10초, 1분, 10분 등의 낮은 간격으로 훨씬 더 쉽고 빠르게 반올림할 수 있는 방법이 있다고 생각합니다.다음과 같이 SUSTR()을 사용하여 타임스탬프를 문자열로 조작해 보십시오.

SELECT 
SUBSTR(datetime(d),1,18)||'0' AS Slot10sec, 
SUBSTR(datetime(d),1,17)||'00' AS Slot1min, 
SUBSTR(datetime(d),1,15)||'0:00' AS Slot10min, 
SUBSTR(datetime(d),1,14)||'00:00' AS Slot1h, 
MY_VALUE
FROM MY_TABLE;

언급URL : https://stackoverflow.com/questions/2192424/round-date-to-10-minutes-interval

반응형