본문 바로가기

📚Study Note/ORACLE

[ ORACLE ] 날짜연산, ADD_MONTH() MONTHS_BETWEEN NEXT_DAY() LAST_DAY() 날짜ROUND() 날짜TRUNC()


-- ※ 날짜 관련 세션 설정 변경
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

--==>>Session이(가) 변경되었습니다.

-- ※ 날짜 연산의 기본 단위는 DAY(일수) 이다. ★
SELECT SYSDATE, SYSDATE+1, SYSDATE-2, SYSDATE+3
FROM DUAL;

/*
2021-03-29 12:04:08	-- 현재
2021-03-30 12:04:08	-- 1일 후
2021-03-27 12:04:08	-- 2일 전
2021-04-01 12:04:08 -- 3일 후

*/

-- ○ 시간 단위 연산
SELECT SYSDATE, SYSDATE + 1/24, SYSDATE - 2/24
FROM DUAL;
/*
2021-03-29 12:06:00     -- 현재	
2021-03-29 13:06:00	    -- 1시간 후
2021-03-29 10:06:00     -- 2시간 전
*/

--● 현재 시간과... 현재 시간 기준 1일 2시간 3분 4초 후를 조회한다.

SELECT SYSDATE "현재시간" , SYSDATE + 1 + 2/24 + 3/(24*60) + 4/(24*60*60) "연산후시간"
FROM DUAL;
--==>>
--     현재시간             연산후시간
--2021-03-29 12:08:35	2021-03-30 14:11:39


-- 방법 2.

SELECT SYSDATE "현재 시간"
        SYSDATE + ((24*60*60) + (2*60*60) + (3*60) + 4) / (24*60*60) "연산 후 시간" 
FROM DUAL;


-- ● 날짜 - 날짜 = 일수

-- EX) 2021-07-09   -  2021-03-29

SELECT TO_DATE('2021-07-09','YYYY-MM-DD') - TO_DATE('2021-03-29','YYYY-MM-DD') "확인"
FROM DUAL;
--==>>102

-- ◎데이터 타입의 변환
SELECT TO_DATE('2021-07-09','YYYY-MM-DD') -- 날짜 형식으로 변환
FROM DUAL;


SELECT TO_DATE('2021-07-59','YYYY-MM-DD') 
FROM DUAL;
--===>> 에러발생


SELECT TO_DATE('2021-13-09','YYYY-MM-DD') 
FROM DUAL;
--===>> 에러발생


-- ※ TO_DATE() 함수를 통해 문자 타입을 날짜 타입으로 변환을 진행할 때
-- 내부적으로 해당 날짜에 대한 유효성 검사가 이루어진다

-- ● ADD_MONTHS() 개월 수를 더해주는 함수
SELECT SYSDATE "1"
    ,  ADD_MONTHS(SYSDATE, 2) "2"
FROM DUAL;
--      현재                        2개월 후
--==>>2021-03-29 12:28:49	2021-05-29 12:28:49  

SELECT SYSDATE "1"
    ,  ADD_MONTHS(SYSDATE, -2) "2개월 전"
FROM DUAL;

--==>> 2021-03-29 12:30:12	2021-01-29 12:30:12
--> 월을 더하고 빼기

-- ※ 날짜 세션 설정 변경
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD';

--==>> Session이(가) 변경되었습니다.



-- ● MONTHS_BETWEEN()
-- 첫 인자값에서 두 번째 인자값을 뺀 개월 수를 반환
SELECT MONTHS_BETWEEN(SYSDATE, TO_DATE('2002-05-31','YYYY-MM-DD'))
FROM DUAL;

--==>>225.95238911290322580645161290322580645


SELECT MONTHS_BETWEEN(SYSDATE, TO_DATE('1996-09-14','YYYY-MM-DD'))
FROM DUAL;

--==>>294.500785170250896057347670250896057348 

--> 개월 수의 차이를 반환하는 함수
-- ※ 결과값의 부호가 - (음수)로 반환되었을 경우에는
-- 첫 번째 인자값에 해당하는 날짜보다 두 번째 인자값에 해당하는 날짜가 미래라는
-- 의미로 파악할 수 있다.

-- ● NEXT_DAY()
-- 첫 번째 인자값을 기준 날짜로 돌아오는 가장 빠른 요일 반환
SELECT NEXT_DAY(SYSDATE,'토')
FROM DUAL;

--==>> 2021-04-03

-- 실무에서 에러나는 경우? 왜그럴까

ALTER SESSION SET NLS_DATE_LANGUAGE = 'ENGLISH';
--==>Session이(가) 변경되었습니다.

SELECT NEXT_DAY(SYSDATE,'토')
FROM DUAL;

--===>> 01846. 00000 -  "not a valid day of the week" 에러

SELECT NEXT_DAY(SYSDATE,'SAT')
FROM DUAL;
--==>>2021-04-03
-- 추가 세션 설정 변경


ALTER SESSION SET NLS_DATE_LANGUAGE = 'KOREAN';
--==>Session이(가) 변경되었습니다.


--Insert Update Delete => COMMIT ROLLBACK 의 대상
--세션변경은 오토커밋 기능이 있다. 


-- ● LAST_DAY()
-- 해당 날짜가 포함되어 있는 그 달의 마지막 날을 반환한다.
SELECT LAST_DAY(SYSDATE)
FROM DUAL;
--===>2021-03-31


-- ● 오늘부로... 정준이가... 군대에 또 끌려(?)간다.
-- 복무기간은 22개월로 한다.

-- 1. 전역일자를 구한다.
-- 2. 하루 꼬박꼬박 3끼 식사를 해야 한다고 가정하면
--    정준이가 몇 끼를 먹어야 집에 보내줄까?


SELECT ADD_MONTHS(SYSDATE,22)
FROM DUAL;

--==>>2023-01-29 14:39:59

--복무기간 *3

--(전역일자 - 현재일자)*3

--
SELECT (TO_DATE('2023-01-29','YYYY-MM-DD') - SYSDATE)*3
FROM DUAL;
--==>>2011.163368055555555555555555555555555556 이게맞는가..



SELECT (ADD_MONTHS(SYSDATE, 22) - SYSDATE) * 3
FROM DUAL;

--==>>2013


-- ● 현재 날짜 및 시각으로부터...
-- 수료일(2021-07-09 18:00:00) 까지 남은 기간을....
-- 다음과 같은 형태로 조회할 수 있도록 한다.
/*
----------------------------------------------------------------------
현재 시각                  | 수료일               | 일  | 시간 | 분 | 초
----------------------------------------------------------------------
2021-03-29 14:34:27        | 2021-07-09 18:00:00  | 110 |  3  |  15 |  33
----------------------------------------------------------------------
*/

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

--==>Session이(가) 변경되었습니다.



SELECT TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS') "현재 시각"
    ,  TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS') "수료일"
    ,  TRUNC(TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS') -(TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS')),0) "일"
    ,  TRUNC((TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS')-((TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS'))+102))*24,0) "시간"
    ,  TRUNC((TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS')-((TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS'))+102+(3/24)))*24*60,0) "분"   
    ,  TRUNC((TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS')-((TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS'))+102+(3/24)+25/(24*60)))*24*60*60,0) "초"
    
    
    
    ,  (TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS') -TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS'))*24*60*60 "둘의 차이"
FROM DUAL;
-- 현재시각                  수료일          일 시간 분 초      둘의 차이(초)
--2021-03-29 14:34:27	2021-07-09 18:00:00	102	3	25	32	8825133.00000000000000000000000000000004




SELECT TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS') "현재 시각"
    ,  TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS') "수료일"
    ,  TRUNC(TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS') -(TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS')),0) "일"
    ,  TRUNC((TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS')-((TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS'))+102))*24,0) "시간"
    ,  TRUNC((TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS')-((TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS'))+102+(3/24)))*24*60,0) "분"   
    ,  MOD((TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS') -TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS'))*24*60*60,60) "초"


    ,  (TO_DATE('2021-07-09 18:00:00','YYYY-MM-DD HH24:MI:SS') -TO_DATE('2021-03-29 14:34:27','YYYY-MM-DD HH24:MI:SS'))*24*60*60 "둘의 차이"
FROM DUAL;




















SELECT (1일) + (2시간) + (3분) + 4초
FROM DUAL;

SELECT (1*24*60*60) + (2*60*60) + (3*60) + 4
FROM DUAL;
--==>> 93784

-- 93784 초를 다시 일, 시간, 분, 초로 환산하면
SELECT MOD(93784, 60) --==>> 4
    ,  MOD(TRUNC(93784/60),60) --==>>3
    ,  MOD(TRUNC(TRUNC(93784/60)/60),24) --===>> 2
    ,  TRUNC(TRUNC(TRUNC(93784/60)/60)/24) --==>> 1
FROM DUAL;




-- 수료일까지 남은 기간 확인(날짜 기준) → 단위: 일수

SELECT 수료일자 - 현재일자
FROM DUAL;

-- T수료일자
SELECT TO_DATE('2021-07-09 18:00:00' ,'YYYY-MM-DD HH24:MI:SS')
FROM DUAL;
--==>> 2021-07-09 18:00:00 (날짜 형식)

SELECT TO_DATE('2021-07-09 18:00:00' ,'YYYY-MM-DD HH24:MI:SS') - SYSDATE
FROM DUAL;
--==>> 102.079386574074074074074074074074074074
-- 수료일까지 남은 일수 (단위 : 일)

SELECT (TO_DATE('2021-07-09 18:00:00' ,'YYYY-MM-DD HH24:MI:SS') - SYSDATE)*24*60*60
FROM DUAL;

--==>> 8819606.99999999999999999999999999999998

SELECT MOD((TO_DATE('2021-07-09 18:00:00' ,'YYYY-MM-DD HH24:MI:SS') - SYSDATE)*24*60*60,60)
FROM DUAL;
--==>> 29




SELECT 

       SYSDATE "현재날짜"
    ,  TO_DATE('2021-07-09 18:00:00' ,'YYYY-MM-DD HH24:MI:SS') "수료날짜"
    ,  MOD((TO_DATE('2021-07-09 18:00:00' ,'YYYY-MM-DD HH24:MI:SS') - SYSDATE)*24*60*60, 60) "초" --==>> 4
    ,  MOD(TRUNC((TO_DATE('2021-07-09 18:00:00' ,'YYYY-MM-DD HH24:MI:SS') - SYSDATE)*24*60*60/60),60)"분" --==>>3
    ,  MOD(TRUNC(TRUNC((TO_DATE('2021-07-09 18:00:00' ,'YYYY-MM-DD HH24:MI:SS') - SYSDATE)*24*60*60/60)/60),24)"시간" --===>> 2
    ,  TRUNC(TRUNC(TRUNC((TO_DATE('2021-07-09 18:00:00' ,'YYYY-MM-DD HH24:MI:SS') - SYSDATE)*24*60*60/60)/60)/24)"일" --==>> 1
FROM DUAL;


--==>> 현재날짜     수료날짜                 





-- 과제

-- 본인이 태어나서 현재까지 얼마만큼의 일, 시간, 분, 초를 살았는지, 살고있는지
-- 조회하는 쿼리문을 구성한다. 



-- ● 날짜 형식 세션 설정 변경
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD';
--==>>Session이(가) 변경되었습니다.


-- ※ 날짜 데이터를 대상으로 반올림, 절삭을 수행할 수 있다.

-- ● 날짜 반올림

SELECT SYSDATE "1"                      --==>>2021-03-29
    ,  ROUND(SYSDATE,'YEAR') "2"        --==>>2021-01-01 : 년도까지만 유효한 데이터(상반기, 하반기 기준)
    ,  ROUND(SYSDATE,'MONTH') "3"       --==>>2021-04-01 : 월까지 유효(15일 기준)
    ,  ROUND(SYSDATE, 'DD') "4"         --==>>2021-03-30 : 일까지 유효(정오 기준)
    ,  ROUND(SYSDATE, 'DAY') "5"        --==>>2021-03-28 : 월화수 는 저번주 일요일, 목금토는 다음주 일요일
                                                            --(날짜까지 유효한 데이터 - 수요일기준)
FROM DUAL;


-- ● 날짜 절삭


SELECT SYSDATE "1"                      --==>>2021-03-29
    ,  TRUNC(SYSDATE,'YEAR') "2"        --==>>2021-01-01 : 년도까지만 유효한 데이터
    ,  TRUNC(SYSDATE,'MONTH') "3"       --==>>2021-03-01 : 월까지 유효
    ,  TRUNC(SYSDATE, 'DD') "4"         --==>>2021-03-29 : 일까지 유효
    ,  TRUNC(SYSDATE, 'DAY') "5"        --==>>2021-03-28 : 저번주 일요일                                                
FROM DUAL;