온풀투데이

[오라클] 하위 컬럼, 서브 쿼리, 인라인 뷰, 뷰(VIEW), RANK(), DENSE_RANK() 본문

DATABASE

[오라클] 하위 컬럼, 서브 쿼리, 인라인 뷰, 뷰(VIEW), RANK(), DENSE_RANK()

온풀 2022. 3. 11. 23:28
20220223_01_scott.sql / 오라클 7일 차

--○ TBL_SAWON 테이블을 활용하여 
--   다음과 같은 항목들을 조회할 수 있도록 쿼리문을 구성한다.
--   사원번호, 사원명, 주민번호, 성별, 입사일

SELECT SANO "사원번호", SANAME "사원명", JUBUN "주민번호"
     , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '3') THEN '남성' 
            WHEN SUBSTR(JUBUN, 7, 1) IN ('2', '4') THEN '여성'
            ELSE '성별확인불가' 
       END "성별"
     , HIREDATE"입사일"
FROM TBL_SAWON;
--==>>
/*
1001    김민성        9707251234567    남성    2005-01-03
1002    서민지        9505152234567    여성    1999-11-23
1003    이지연        9905192234567    여성    2006-08-10
1004    이연주        9508162234567    여성    2007-10-10
1005    오이삭        9805161234567    남성    2007-10-10
1006    이현이        8005132234567    여성    1999-10-10
1007    박한이        0204053234567    남성    2010-10-10
1008    선동렬        6803171234567    남성    1998-10-10
1009    선우용녀    6912232234567    여성    1998-10-10
1010    선우선        0303044234567    여성    2010-10-10
1011    남주혁        0506073234567    남성    2012-10-10
1012    남궁민        0208073234567    남성    2012-10-10
1013    남진        6712121234567    남성    1998-10-10
1014    홍수민        0005044234567    여성    2015-10-10
1015    임소민        9711232234567    여성    2007-10-10
1016    이이경        0603194234567    여성    2015-01-20
*/


--○ TBL_SAWON 테이블을 활용하여 
--   다음과 같은 항목들을 조회할 수 있도록 쿼리문을 구성한다.
--   『사원번호, 사원명, 주민번호, 성별, 현재나이, 입사일, 
--     정년퇴직일, 근무일수, 남은일수, 급여, 보너스』
--   단, 현재나이는 기본 한국나이 계산법에 따라 연산을 수행한다.
--   또한, 정년퇴직일은 해당 직원의 나이가 한국나이로 60세가 되는 해의
--   그 직원의 입사 월, 일로 연산을 수행한다.
--   그리고, 보너스는 1000일 이상 2000일 미만 근무한 사원은
--   그 사원의 원래 급여 기준 30% 지급, 2000일 이상 근무한 사원은
--   그 사원의 원래 급여 기준 50% 지급을 할 수 있도록 처리한다.

--EX) 1001 김민성 9707251234567 남성 26 2005-01-03 2056-01-03 212121 2232323 3000 1500

-- 내 풀이 ---------------------------------------------------------------------
-- 남은일수 수정해야 함!!!
/*
SELECT SANO "사원번호", SANAME "사원명", JUBUN "주민번호", 
       CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '3') THEN '남성' 
            WHEN SUBSTR(JUBUN, 7, 1) IN ('2', '4') THEN '여성'
            ELSE '성별 확인불가' 
       END "성별",  
       CASE WHEN TO_NUMBER(SUBSTR(JUBUN, 1, 1)) > 0 
            THEN TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')) - TO_NUMBER('19'||(SUBSTR(JUBUN, 1, 2))) + 1
            WHEN TO_NUMBER(SUBSTR(JUBUN, 1, 1)) = 0 
            THEN TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')) - TO_NUMBER('20'||(SUBSTR(JUBUN, 1, 2))) + 1
            ELSE 0 
       END "현재나이"
       , HIREDATE "입사일", 
       CASE WHEN TO_NUMBER(SUBSTR(JUBUN, 1, 1)) > 0 
            THEN TO_CHAR(ADD_MONTHS(SYSDATE, ((60 - (TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')) - TO_NUMBER('19'||(SUBSTR(JUBUN, 1, 2))) + 1))*12)), 'YYYY') || '-' || TO_CHAR(HIREDATE, 'MM-DD') 
            WHEN TO_NUMBER(SUBSTR(JUBUN, 1, 1)) = 0 
            THEN TO_CHAR(ADD_MONTHS(SYSDATE, ((60 - (TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')) - TO_NUMBER('20'||(SUBSTR(JUBUN, 1, 2))) + 1))*12)), 'YYYY') || '-' || TO_CHAR(HIREDATE, 'MM-DD')
            ELSE '정년퇴직일 확인불가' 
       END "정년퇴직일"
       , TRUNC(SYSDATE - HIREDATE) "근무일수", 
       CASE WHEN TO_NUMBER(SUBSTR(JUBUN, 1, 1)) > 0 
            THEN TRUNC(ADD_MONTHS(SYSDATE, ((60 - (TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')) - TO_NUMBER('19'||(SUBSTR(JUBUN, 1, 2))) + 1))*12)) - SYSDATE)
            WHEN TO_NUMBER(SUBSTR(JUBUN, 1, 1)) = 0 
            THEN TRUNC(ADD_MONTHS(SYSDATE, ((60 - (TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')) - TO_NUMBER('20'||(SUBSTR(JUBUN, 1, 2))) + 1))*12)) - SYSDATE)
            ELSE 0 
       END "남은일수", 
       SAL "급여", 
       CASE WHEN TRUNC(SYSDATE - HIREDATE) >= 1000 AND TRUNC(SYSDATE - HIREDATE) < 2000
            THEN SAL * 0.3
            WHEN TRUNC(SYSDATE - HIREDATE) >= 2000
            THEN SAL * 0.5
            ELSE 0
       END "보너스"
FROM TBL_SAWON;

-- 보너스 구하기
SELECT CASE WHEN TRUNC(SYSDATE - HIREDATE) >= 1000 AND TRUNC(SYSDATE - HIREDATE) < 2000
            THEN TO_CHAR(SAL * 0.3)
            WHEN TRUNC(SYSDATE - HIREDATE) >= 2000
            THEN TO_CHAR(SAL * 0.5)
            ELSE '보너스 판정불가'
       END "보너스"
FROM TBL_SAWON;

-- 정년퇴직일 구하기
SELECT TO_CHAR(ADD_MONTHS(SYSDATE, ((60 - (TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')) - TO_NUMBER('19'||(SUBSTR(JUBUN, 1, 2))) + 1))*12)), 'YYYY') || '-' || TO_CHAR(HIREDATE, 'MM-DD')
FROM TBL_SAWON
WHERE SANAME = '김민성';

SELECT (60 - (TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')) - TO_NUMBER('19'||(SUBSTR(JUBUN, 1, 2))) + 1)) 
FROM TBL_SAWON
WHERE SANAME = '김민성';

-- 현재나이 구하기
SELECT CASE WHEN TO_NUMBER(SUBSTR(JUBUN, 1, 1)) > 0 
            THEN TO_CHAR(TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')) - TO_NUMBER('19'||(SUBSTR(JUBUN, 1, 2))) + 1)  
            ELSE '성별확인불가' 
       END "현재나이"
FROM TBL_SAWON;

SELECT TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')) - TO_NUMBER('19'||(SUBSTR(JUBUN, 1, 2))) + 1   
FROM TBL_SAWON
WHERE SANAME = '김민성';

SELECT CASE WHEN TO_NUMBER(SUBSTR(JUBUN, 1, 1)) > 0  THEN '1' 
            ELSE '성별확인불가' 
       END "성별"
FROM TBL_SAWON
*/

SELECT *
FROM TBL_SAWON;

-- 수업 풀이

-- 사원번호, 사원명, 주민번호, 성별, 현재나이, 입사일, 급여 ... 먼저
SELECT SANO "사원번호", SANAME "사원명", JUBUN "주민번호"
    -- 성별
     , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '3') THEN '남성'
            WHEN SUBSTR(JUBUN, 7, 1) IN ('2', '4') THEN '여성'
            ELSE '성별확인불가'
       END "성별"
    -- 현재나이 = 현재년도 - 태어난년도 + 1 (1900년대 / 2000년대)
     , CASE WHEN 1900년대생이라면 THEN 현재년도 - (주민번호앞두자리 + 1899) 
            WHEN 1900년대생이라면 THEN 현재년도 - (주민번호앞두자리 + 1999) 
            ELSE END "현재나이"
FROM TBL_SAWON;

SELECT SANO "사원번호", SANAME "사원명", JUBUN "주민번호"
    -- 성별
     , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '3') THEN '남성'
            WHEN SUBSTR(JUBUN, 7, 1) IN ('2', '4') THEN '여성'
            ELSE '성별확인불가'
       END "성별"
    -- 현재나이 = 현재년도 - 태어난년도 + 1 (1900년대 / 2000년대)
     , CASE WHEN 주민번호 7번째자리 1개가 '1'또는 '2' 
            THEN 현재년도 - (주민번호앞두자리 + 1899) 
            WHEN 주민번호 7번째자리 1개가 '3'또는 '4' 
            THEN 현재년도 - (주민번호앞두자리 + 1999) 
            ELSE -1 
       END "현재나이"

FROM TBL_SAWON;

SELECT SANO "사원번호", SANAME "사원명", JUBUN "주민번호"
    -- 성별
     , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '3') THEN '남성'
            WHEN SUBSTR(JUBUN, 7, 1) IN ('2', '4') THEN '여성'
            ELSE '성별확인불가'
       END "성별"
    -- 현재나이 = 현재년도 - 태어난년도 + 1 (1900년대 / 2000년대)
     , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '2') 
            THEN EXTRACT(YEAR FROM SYSDATE) - (주민번호앞두자리 + 1899) 
            WHEN SUBSTR(JUBUN, 7, 1) IN ('3', '4') 
            THEN EXTRACT(YEAR FROM SYSDATE) - (주민번호앞두자리 + 1999) 
            ELSE -1 
       END "현재나이"

FROM TBL_SAWON;

SELECT SANO "사원번호", SANAME "사원명", JUBUN "주민번호"
    -- 성별
     , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '3') THEN '남성'
            WHEN SUBSTR(JUBUN, 7, 1) IN ('2', '4') THEN '여성'
            ELSE '성별확인불가'
       END "성별"
    -- 현재나이 = 현재년도 - 태어난년도 + 1 (1900년대 / 2000년대)
     , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '2') 
            THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1899) 
            WHEN SUBSTR(JUBUN, 7, 1) IN ('3', '4') 
            THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1999) 
            ELSE -1 
       END "현재나이"
    -- 입사일
     , HIREDATE "입사일"   
    -- 급여
     , SAL
FROM TBL_SAWON;

--● 하위 컬럼???? FROM 안에 SELECT 문 넣어 버리기!!!

SELECT EMPNO, ENAME, SAL, COMM, SAL*12+NVL(COMM, 0) "연봉"
FROM EMP;

SELECT EMPNO, ENAME, SAL, COMM, SAL*12+NVL(COMM, 0) "연봉", 연봉*2 "두배연봉"
FROM EMP;
--==> 에러 발생
--    (ORA-00904: "연봉": invalid identifier)

SELECT T.EMPNO, T.ENAME, T.SAL, T.연봉, T.연봉*2 "두배연봉"
FROM
(
    SELECT EMPNO, ENAME, SAL, COMM, SAL*12+NVL(COMM, 0) "연봉"
    FROM EMP
) T;

SELECT T.*
FROM
(
    SELECT EMPNO, ENAME, SAL, COMM, SAL*12+NVL(COMM, 0) "연봉"
    FROM EMP
) T;


-- 사원번호, 사원명, 주민번호, 성별, 현재나이, 입사일, 
-- , 정년퇴직일, 근무일수, 남은일수, 급여, 보너스
SELECT T.사원번호, T.사원명, T.주민번호, T.성별, T.현재나이, T.입사일
    -- 정년퇴직일
    -- 정년퇴직년도 → 해당 직원의 나이가 한국나이로 60세가 되는 해
    -- 현재 나이가... 57세...  3년 후        2022 → 2025
    -- 현재 나이가... 28세... 32년 후        2022 → 2054
    -- ADD_MONTHS(SYSDATE, 남은년수*12)
    --                     --------
    --                      60 - 현재나이
    -- ADD_MONTHS(SYSDATE, (60 - 현재나이) * 12) → 특정날짜
    -- TO_CHAR('특정날짜', 'YYYY')     → 정년퇴직 년도만 문자타입으로 추출
    -- TO_CHAR(입사일, 'MM-DD')        → 입사 월일만 문자타입으로 추출
    -- TO_CHAR('특정날짜', 'YYYY') || '-' || TO_CHAR(입사일, 'MM-DD') "정년퇴직일"
    -- TO_CHAR(ADD_MONTHS(SYSDATE, (60 - 현재나이) * 12), 'YYYY') || '-' || TO_CHAR(입사일, 'MM-DD') "정년퇴직일"
    , TO_CHAR(ADD_MONTHS(SYSDATE, (60 - T.현재나이) * 12), 'YYYY') || '-' || TO_CHAR(T.입사일, 'MM-DD') "정년퇴직일"

    -- 근무일수
    -- 근무일수 = 현재일 - 입사일
     , TRUNC(SYSDATE - T.입사일) "근무일수"

    -- 남은일수
    -- 남은일수 = 정년퇴직일 - 현재일
     , TRUNC(TO_DATE(TO_CHAR(ADD_MONTHS(SYSDATE, (60 - T.현재나이) * 12), 'YYYY') || '-' || TO_CHAR(T.입사일, 'MM-DD'), 'YYYY-MM-DD') - SYSDATE) "남은일수"

    -- 급여
    , T.급여

    -- 보너스
    -- 근무일수가 1000일 이상 2000일 미만 → 원래 급여의 30% 지급
    -- 근무일수가 2000일 이상             → 원래 급여의 50% 지급
    -- 나머지                             → 0     
    -------------------------------------------------------------
    -- 근무일수 2000일 이상               → T.급여 * 0.5
    -- 근무일수 1000일 이상               → T.급여 * 0.3
    -- 나머지                             → 0     
    -------------------------------------------------------------
    , CASE WHEN TRUNC(SYSDATE - T.입사일) >= 2000 THEN T.급여 * 0.5
           WHEN TRUNC(SYSDATE - T.입사일) >= 1000 THEN T.급여 * 0.3
           ELSE 0
      END "보너스"
FROM 
(
    SELECT SANO "사원번호", SANAME "사원명", JUBUN "주민번호"
        -- 성별
         , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '3') THEN '남성'
                WHEN SUBSTR(JUBUN, 7, 1) IN ('2', '4') THEN '여성'
                ELSE '성별확인불가'
           END "성별"
        -- 현재나이 = 현재년도 - 태어난년도 + 1 (1900년대 / 2000년대)
         , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '2') 
                THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1899) 
                WHEN SUBSTR(JUBUN, 7, 1) IN ('3', '4') 
                THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1999) 
                ELSE -1 
           END "현재나이"
        -- 입사일
         , HIREDATE "입사일"   
        -- 급여
         , SAL "급여"
    FROM TBL_SAWON
) T;
--==>>
/*
1001    김민성        9707251234567    남성    26    2005-01-03    2056-01-03    6260    12366    3000    1500
1002    서민지        9505152234567    여성    28    1999-11-23    2054-11-23    8128    11960    4000    2000
1003    이지연        9905192234567    여성    24    2006-08-10    2058-08-10    5676    13316    3000    1500
1004    이연주        9508162234567    여성    28    2007-10-10    2054-10-10    5250    11916    4000    2000
1005    오이삭        9805161234567    남성    25    2007-10-10    2057-10-10    5250    13012    4000    2000
1006    이현이        8005132234567    여성    43    1999-10-10    2039-10-10    8172     6437    1000     500
1007    박한이        0204053234567    남성    21    2010-10-10    2061-10-10    4154    14473    1000     500
1008    선동렬        6803171234567    남성    55    1998-10-10    2027-10-10    8537     2054    1500     750
1009    선우용녀    6912232234567    여성    54    1998-10-10    2028-10-10    8537     2420    1300     650
1010    선우선        0303044234567    여성    20    2010-10-10    2062-10-10    4154    14838    1600     800
1011    남주혁        0506073234567    남성    18    2012-10-10    2064-10-10    3423    15569    2600    1300
1012    남궁민        0208073234567    남성    21    2012-10-10    2061-10-10    3423    14473    2600    1300
1013    남진        6712121234567    남성    56    1998-10-10    2026-10-10    8537     1689    2200    1100
1014    홍수민        0005044234567    여성    23    2015-10-10    2059-10-10    2328    13742    5200    2600
1015    임소민        9711232234567    여성    26    2007-10-10    2056-10-10    5250    12647    5500    2750
1016    이이경        0603194234567    여성    17    2015-01-20    2065-01-20    2591    15671    1500     750
*/
--==>> 인라인 뷰!!! 라고 함 (FROM 절에서 쓰는 서브 쿼리)

--○ TBL_SAWON 테이블에 데이터 추가 입력
INSERT INTO TBL_SAWON(SANO, SANAME, JUBUN, HIREDATE, SAL)
VALUES(1017, '이호석', '9611121234567', SYSDATE, 5000); 
--==>> 1 행 이(가) 삽입되었습니다.

--○ 확인
SELECT *
FROM TBL_SAWON;

--○ 커밋
COMMIT;
--==>> 커밋 완료.

SELECT T.사원번호, T.사원명, T.주민번호, T.성별, T.현재나이, T.입사일
    , TO_CHAR(ADD_MONTHS(SYSDATE, (60 - T.현재나이) * 12), 'YYYY') || '-' || TO_CHAR(T.입사일, 'MM-DD') "정년퇴직일"
     , TRUNC(SYSDATE - T.입사일) "근무일수"
     , TRUNC(TO_DATE(TO_CHAR(ADD_MONTHS(SYSDATE, (60 - T.현재나이) * 12), 'YYYY') || '-' || TO_CHAR(T.입사일, 'MM-DD'), 'YYYY-MM-DD') - SYSDATE) "남은일수"
    , T.급여
    , CASE WHEN TRUNC(SYSDATE - T.입사일) >= 2000 THEN T.급여 * 0.5
           WHEN TRUNC(SYSDATE - T.입사일) >= 1000 THEN T.급여 * 0.3
           ELSE 0
      END "보너스"
FROM 
(
    SELECT SANO "사원번호", SANAME "사원명", JUBUN "주민번호"
         , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '3') THEN '남성'
                WHEN SUBSTR(JUBUN, 7, 1) IN ('2', '4') THEN '여성'
                ELSE '성별확인불가'
           END "성별"
         , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '2') 
                THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1899) 
                WHEN SUBSTR(JUBUN, 7, 1) IN ('3', '4') 
                THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1999) 
                ELSE -1 
           END "현재나이"
         , HIREDATE "입사일"   
         , SAL "급여"
    FROM TBL_SAWON
) T;
--==>>
/*
1001    김민성        9707251234567    남성    26    2005-01-03    2056-01-03    6260    12366    3000    1500
1002    서민지        9505152234567    여성    28    1999-11-23    2054-11-23    8128    11960    4000    2000
1003    이지연        9905192234567    여성    24    2006-08-10    2058-08-10    5676    13316    3000    1500
1004    이연주        9508162234567    여성    28    2007-10-10    2054-10-10    5250    11916    4000    2000
1005    오이삭        9805161234567    남성    25    2007-10-10    2057-10-10    5250    13012    4000    2000
1006    이현이        8005132234567    여성    43    1999-10-10    2039-10-10    8172     6437    1000     500
1007    박한이         0204053234567    남성    21    2010-10-10    2061-10-10    4154    14473    1000     500
1008    선동렬        6803171234567    남성    55    1998-10-10    2027-10-10    8537     2054    1500     750
1009    선우용녀    6912232234567    여성    54    1998-10-10    2028-10-10    8537     2420    1300     650
1010    선우선        0303044234567    여성    20    2010-10-10    2062-10-10    4154    14838    1600     800
1011    남주혁        0506073234567    남성    18    2012-10-10    2064-10-10    3423    15569    2600    1300
1012    남궁민        0208073234567    남성    21    2012-10-10    2061-10-10    3423    14473    2600    1300
1013    남진        6712121234567    남성    56    1998-10-10    2026-10-10    8537     1689    2200    1100
1014    홍수민        0005044234567    여성    23    2015-10-10    2059-10-10    2328    13742    5200    2600
1015    임소민        9711232234567    여성    26    2007-10-10    2056-10-10    5250    12647    5500    2750
1016    이이경        0603194234567    여성    17    2015-01-20    2065-01-20    2591    15671    1500     750
1017    이호석        9611121234567    남성    27    2022-02-23    2055-02-23       0    12052    5000       0
*/


-- 위에서 처리한 내용을 기반으로 
-- 특정 근무일수의 사원을 확인해야 한다거나...
-- 특정 보너스 금액을 받는 사원을 확인해야 할 경우가 발생할 수 있다.
-- 이와 같은 경우... 해당 쿼리문을 다시 구성해야 하는 번거로움을 줄일 수 있도록
-- 뷰(VIEW)를 만들어 저장해 둘 수 있다.

CREATE TABLE TBL_SAWON;
-- 이 테이블은 이미 있으니 못 만드는데요???? 하고 에러남
-- 이미 존재한다...

CREATE OR REPLACE TABLE TBL_SAWON;
-- 이것도 에러남

-- 엄밀히 말하면 쿼리문이 저장되는 것, 데이터 저장이 아니라 이런 각도를 보고 싶어! 하는 거
CREATE OR REPLACE VIEW VIEW_SAWON -- 이미 만들어져 있더라도 덮어쓰기 됨
AS
SELECT T.사원번호, T.사원명, T.주민번호, T.성별, T.현재나이, T.입사일
    , TO_CHAR(ADD_MONTHS(SYSDATE, (60 - T.현재나이) * 12), 'YYYY') || '-' || TO_CHAR(T.입사일, 'MM-DD') "정년퇴직일"
     , TRUNC(SYSDATE - T.입사일) "근무일수"
     , TRUNC(TO_DATE(TO_CHAR(ADD_MONTHS(SYSDATE, (60 - T.현재나이) * 12), 'YYYY') || '-' || TO_CHAR(T.입사일, 'MM-DD'), 'YYYY-MM-DD') - SYSDATE) "남은일수"
    , T.급여
    , CASE WHEN TRUNC(SYSDATE - T.입사일) >= 2000 THEN T.급여 * 0.5
           WHEN TRUNC(SYSDATE - T.입사일) >= 1000 THEN T.급여 * 0.3
           ELSE 0
      END "보너스"
FROM 
(
    SELECT SANO "사원번호", SANAME "사원명", JUBUN "주민번호"
         , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '3') THEN '남성'
                WHEN SUBSTR(JUBUN, 7, 1) IN ('2', '4') THEN '여성'
                ELSE '성별확인불가'
           END "성별"
         , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '2') 
                THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1899) 
                WHEN SUBSTR(JUBUN, 7, 1) IN ('3', '4') 
                THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1999) 
                ELSE -1 
           END "현재나이"
         , HIREDATE "입사일"   
         , SAL "급여"
    FROM TBL_SAWON
) T;
--==>> 에러 발생
--     (ORA-01031: insufficient privileges)

--○ SYS로 부터 CREATE VIEW 권한을 부여받은 이후 다시 실행
--==>> View VIEW_SAWON이(가) 생성되었습니다.

SELECT *
FROM VIEW_SAWON;

SELECT *
FROM VIEW_SAWON
WHERE 근무일수 >= 6000;

SELECT *
FROM VIEW_SAWON
WHERE 남은일수 >= 15000;

SELECT *
FROM VIEW_SAWON
WHERE 보너스 >= 2000;


--○ VIEW 생성 이후 TBL_SAWON 테이블에 데이터 추가 입력
INSERT INTO TBL_SAWON(SANO, SANAME, JUBUN, HIREDATE, SAL)
VALUES(1018, '신시은', '9910312234567', SYSDATE, 5000); 
--==>> 1 행 이(가) 삽입되었습니다.

SELECT *
FROM VIEW_SAWON;
--==>>
/*
1001    김민성        9707251234567    남성    26    2005-01-03    2056-01-03    6260    12366    3000    1500
1002    서민지        9505152234567    여성    28    1999-11-23    2054-11-23    8128    11960    4000    2000
1003    이지연        9905192234567    여성    24    2006-08-10    2058-08-10    5676    13316    3000    1500
1004    이연주        9508162234567    여성    28    2007-10-10    2054-10-10    5250    11916    4000    2000
1005    오이삭        9805161234567    남성    25    2007-10-10    2057-10-10    5250    13012    4000    2000
1006    이현이        8005132234567    여성    43    1999-10-10    2039-10-10    8172     6437    1000     500
1007    박한이        0204053234567    남성    21    2010-10-10    2061-10-10    4154    14473    1000     500
1008    선동렬        6803171234567    남성    55    1998-10-10    2027-10-10    8537     2054    1500     750
1009    선우용녀    6912232234567    여성    54    1998-10-10    2028-10-10    8537     2420    1300     650
1010    선우선        0303044234567    여성    20    2010-10-10    2062-10-10    4154    14838    1600     800
1011    남주혁        0506073234567    남성    18    2012-10-10    2064-10-10    3423    15569    2600    1300
1012    남궁민        0208073234567    남성    21    2012-10-10    2061-10-10    3423    14473    2600    1300
1013    남진        6712121234567    남성    56    1998-10-10    2026-10-10    8537     1689    2200    1100
1014    홍수민        0005044234567    여성    23    2015-10-10    2059-10-10    2328    13742    5200    2600
1015    임소민        9711232234567    여성    26    2007-10-10    2056-10-10    5250    12647    5500    2750
1016    이이경        0603194234567    여성    17    2015-01-20    2065-01-20    2591    15671    1500     750
1017    이호석        9611121234567    남성    27    2022-02-23    2055-02-23       0    12052    5000       0  → CHECK~!!!
1018    신시은        9910312234567    여성    24    2022-02-23    2058-02-23       0    13148    5000       0  → CHECK~!!!
*/

--------------------------------------------------------------------------------
--○ 서브쿼리를 활용하여
--   TBL_SAWON 테이블을 다음과 같이 조회할 수 있도록 한다.
/*
-------------------------------------
사원명 성별 현재나이 급여 나이보너스
-------------------------------------

단, 나이 보너스는 현재 나이가 50세 이상이면 급여의 70%
    40세 이상 50세 미만이면 급여의 50%
    20세 이상 40세 미만이면 급여의 30% 로 한다.

또한, 완성된 조회 구문을 통해
VIEW_SAWON2 라는 이름의 뷰(VIEW) 를 생성한다.
*/

-- 내 풀이
-- TBL_SAWON 테이블 조회
SELECT *
FROM TBL_SAWON;

SELECT T.*
     , CASE WHEN T.현재나이 >= 50 THEN T.급여 * 0.7 
            WHEN T.현재나이 >= 40 THEN T.급여 * 0.5
            WHEN T.현재나이 >= 20 THEN T.급여 * 0.3 
            ELSE 0
       END "나이보너스"
FROM 
(
    SELECT SANAME "사원명" 
         , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '3') THEN '남성'
                WHEN SUBSTR(JUBUN, 7, 1) IN ('2', '4') THEN '여성'
                ELSE '성별확인불가'
           END "성별" 
         , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '2') 
                THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1899) 
                WHEN SUBSTR(JUBUN, 7, 1) IN ('3', '4') 
                THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1999) 
                ELSE -1 
           END "현재나이" 
         , SAL "급여" 
    FROM TBL_SAWON -- 여기 세미콜론 쓰면 에러난다!!!!!
) T;
--==>>
/*
김민성        남성    26    3000     900
서민지        여성    28    4000    1200
이지연        여성    24    3000     900
이연주        여성    28    4000    1200
오이삭        남성    25    4000    1200
이현이        여성    43    1000     500
박한이        남성    21    1000     300
선동렬        남성    55    1500    1050
선우용녀    여성    54    1300     910
선우선        여성    20    1600     480
남주혁        남성    18    2600       0
남궁민        남성    21    2600     780
남진        남성    56    2200    1540
홍수민        여성    23    5200    1560
임소민        여성    26    5500    1650
이이경        여성    17    1500       0
이호석        남성    27    5000    1500
신시은        여성    24    5000    1500
*/

-- VIEW_SAWON2 뷰 생성
CREATE OR REPLACE VIEW VIEW_SAWON2 
AS
SELECT T.*
     , CASE WHEN T.현재나이 >= 50 THEN T.급여 * 0.7 
            WHEN T.현재나이 >= 40 THEN T.급여 * 0.5
            WHEN T.현재나이 >= 20 THEN T.급여 * 0.3 
            ELSE 0
       END "나이보너스"
FROM 
(
    SELECT SANAME "사원명" 
         , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '3') THEN '남성'
                WHEN SUBSTR(JUBUN, 7, 1) IN ('2', '4') THEN '여성'
                ELSE '성별확인불가'
           END "성별" 
         , CASE WHEN SUBSTR(JUBUN, 7, 1) IN ('1', '2') 
                THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1899) 
                WHEN SUBSTR(JUBUN, 7, 1) IN ('3', '4') 
                THEN EXTRACT(YEAR FROM SYSDATE) - (TO_NUMBER(SUBSTR(JUBUN, 1, 2)) + 1999) 
                ELSE -1 
           END "현재나이" 
         , SAL "급여" 
    FROM TBL_SAWON -- 여기 세미콜론 쓰면 에러난다!!!!!
) T;
--==>> View VIEW_SAWON2이(가) 생성되었습니다.

--○ 생성한 뷰(VIEW) 확인(조회)
SELECT *
FROM VIEW_SAWON2;

--------------------------------------------------------------------------------

--○ RANK() → 등수(순위)를 반환하는 함수 -- 분석 함수 / 파라미터 값은 OVER()안에
SELECT EMPNO "사원번호", ENAME "사원명", DEPTNO "부서번호", SAL "급여"
     , RANK() OVER(ORDER BY SAL DESC) "전체급여순위"
FROM EMP;
--==>>
/*
7839    KING    10    5000     1
7902    FORD    20    3000     2
7788    SCOTT    20    3000     2
7566    JONES    20    2975     4
7698    BLAKE    30    2850     5
7782    CLARK    10    2450     6
7499    ALLEN    30    1600     7
7844    TURNER    30    1500     8
7934    MILLER    10    1300     9
7521    WARD    30    1250    10
7654    MARTIN    30    1250    10
7876    ADAMS    20    1100    12
7900    JAMES    30     950    13
7369    SMITH    20     800    14
*/

SELECT EMPNO "사원번호", ENAME "사원명", DEPTNO "부서번호", SAL "급여"
     , RANK() OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) "부서별급여순위" --파티션 -> 나누는 거, 분할 --> 나눠서 구분하겠다
     , RANK() OVER(ORDER BY SAL DESC) "전체급여순위"
FROM EMP;
--==>>
/*
7839    KING    10    5000    1     1
7902    FORD    20    3000    1     2
7788    SCOTT    20    3000    1     2
7566    JONES    20    2975    3     4
7698    BLAKE    30    2850    1     5
7782    CLARK    10    2450    2     6
7499    ALLEN    30    1600    2     7
7844    TURNER    30    1500    3     8
7934    MILLER    10    1300    3     9
7521    WARD    30    1250    4    10
7654    MARTIN    30    1250    4    10
7876    ADAMS    20    1100    4    12
7900    JAMES    30     950    6    13
7369    SMITH    20     800    5    14
*/

SELECT EMPNO "사원번호", ENAME "사원명", DEPTNO "부서번호", SAL "급여"
     , RANK() OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) "부서별급여순위" --파티션 -> 나누는 거, 분할 --> 나눠서 구분하겠다
     , RANK() OVER(ORDER BY SAL DESC) "전체급여순위"
FROM EMP
ORDER BY DEPTNO;
--==>>
/*
7839    KING    10    5000    1     1
7782    CLARK    10    2450    2     6
7934    MILLER    10    1300    3     9
7902    FORD    20    3000    1     2
7788    SCOTT    20    3000    1     2
7566    JONES    20    2975    3     4
7876    ADAMS    20    1100    4    12
7369    SMITH    20     800     5    14
7698    BLAKE    30    2850    1     5
7499    ALLEN    30    1600    2     7
7844    TURNER    30    1500    3     8
7654    MARTIN    30    1250    4    10
7521    WARD    30    1250    4    10
7900    JAMES    30     950    6    13
*/

--○ DENSE_RANK() → 서열을 반환하는 함수 -- 순위는 공동 1등이 있는데 얘는 그냥 순서대로 ...
SELECT EMPNO "사원번호", ENAME "사원명", DEPTNO "부서번호", SAL "급여"
     , DENSE_RANK() OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) "부서별급여순위" 
     , DENSE_RANK() OVER(ORDER BY SAL DESC) "전체급여순위"
FROM EMP
ORDER BY DEPTNO;
--==>>
/*
7839    KING    10    5000    1     1
7782    CLARK    10    2450    2     5
7934    MILLER    10    1300    3     8
7902    FORD    20    3000    1     2
7788    SCOTT    20    3000    1     2
7566    JONES    20    2975    2     3
7876    ADAMS    20    1100    3    10
7369    SMITH    20     800    4    12
7698    BLAKE    30    2850    1     4
7499    ALLEN    30    1600    2     6
7844    TURNER    30    1500    3     7
7654    MARTIN    30    1250    4     9
7521    WARD    30    1250    4     9
7900    JAMES    30     950    5    11
*/

--○ EMP 테이블의 사원 데이터를
--   사원명, 부서번호, 연봉, 부서내연봉순위, 전체연봉순위 항목으로 조회한다.
SELECT *
FROM TBL_EMP;

SELECT T.*, RANK() OVER(PARTITION BY T.부서번호 ORDER BY T.연봉 DESC) "부서내연봉순위"
          , RANK() OVER(ORDER BY T.연봉 DESC) "전체연봉순위"
FROM
(
    SELECT ENAME "사원명", DEPTNO "부서번호", COALESCE(SAL*12+COMM, SAL*12, COMM, 0) "연봉"
    FROM TBL_EMP
    ORDER BY DEPTNO
) T;

-- 수업 풀이
SELECT ENAME "사원명", DEPTNO "부서번호", SAL*12+NVL(COMM, 0) "연봉"
     , RANK() OVER(PARTITION BY DEPTNO ORDER BY (SAL*12+NVL(COMM, 0)) DESC) "부서내연봉순위"
     , RANK() OVER(ORDER BY (SAL*12+NVL(COMM, 0)) DESC) "전체연봉순위"
FROM EMP;

SELECT T.*
     , RANK() OVER(PARTITION BY T.부서번호 ORDER BY T.연봉) "부서내연봉순위"
     , RANK() OVER(ORDER BY T.연봉 DESC) "전체연봉순위"
FROM
(
    SELECT ENAME "사원명", DEPTNO "부서번호", SAL*12+NVL(COMM, 0) "연봉"
    FROM EMP
) T;
--==>>
/*
KING    10    60000    3     1
SCOTT    20    36000    4     2
FORD    20    36000    4     2
JONES    20    35700    3     4
BLAKE    30    34200    6     5
CLARK    10    29400    2     6
ALLEN    30    19500    5     7
TURNER    30    18000    4     8
MARTIN    30    16400    3     9
MILLER    10    15600    1    10
WARD    30    15500    2    11
ADAMS    20    13200    2    12
JAMES    30    11400    1    13
SMITH    20    9600    1    14
*/


--○ EMP 테이블에서 전체 연봉 등수(순위)가 1등부터 5등까지만...
--   사원명, 부서번호, 연봉, 전체연봉순위 항목으로 조회한다.
SELECT T.*
FROM
(
    SELECT ENAME "사원명", DEPTNO "부서번호", SAL*12+NVL(COMM, 0) "연봉"
         , RANK() OVER(ORDER BY (SAL*12+NVL(COMM, 0)) DESC) "전체연봉순위"
    FROM EMP
) T
WHERE T.전체연봉순위 >= 1 AND T.전체연봉순위 <= 5
ORDER BY T.전체연봉순위;

-- 수업 풀이--------------------------------------------------------------------
SELECT 사원명, 부서번호, 연봉, 전체연봉순위
FROM EMP
WHERE 전체 연봉 등수(순위)가 1등부터 5등;

SELECT ENAME "사원명", DEPTNO "부서번호", SAL*12+NVL(COMM, 0) "연봉"
     , RANK() OVER(ORDER BY (연봉) DESC) "전체연봉순위"
FROM EMP
WHERE 전체 연봉 등수(순위)가 1등부터 5등;

SELECT ENAME "사원명", DEPTNO "부서번호", SAL*12+NVL(COMM, 0) "연봉"
     , RANK() OVER(ORDER BY (SAL*12+NVL(COMM, 0)) DESC) "전체연봉순위"
FROM EMP
WHERE RANK() OVER(ORDER BY (SAL*12+NVL(COMM, 0)) DESC) <= 5;
--==> 에러 발생
--    (ORA-30483: window  functions are not allowed here)
-- ★ 주목해야 할 에러 
-- 윈도우 함수를 여기서 사용할 수 없다! --> 윈도우 함수 -> 분석 함수!!!
-- 분석함수는 WHERE 절에서 못 씀

--※ 위의 내용은 RANK() OVER() 와 같은 분석 함수를 WHERE 절에서 사용한 경우이며...
--   이 함수는 WHERE 조건절에서 사용할 수 없기 때문에 발생하는 에러이다.
--   이 경우, 우리는 INLINE VIEW를 활용해서 풀이해야 한다.
SELECT T.*
FROM
(
    SELECT ENAME "사원명", DEPTNO "부서번호", SAL*12+NVL(COMM, 0) "연봉"
         , RANK() OVER(ORDER BY (SAL*12+NVL(COMM, 0)) DESC) "전체연봉순위"
    FROM EMP
) T
WHERE T.전체연봉순위 <= 5;
--==>>
/*
KING    10    60000    1
SCOTT    20    36000    2
FORD    20    36000    2
JONES    20    35700    4
BLAKE    30    34200    5
*/

--○ EMP 테이블에서 각 부서별로 연봉등수가 1등부터 2등까지만 조회한다.
--   사원명, 부서번호, 연봉, 부서내연봉등수, 전체연봉등수 
--   항목을 조회할 수 있도록 쿼리문을 구성한다.
SELECT *
FROM EMP;

SELECT 사원명, 부서번호, 연봉, 부서내연봉등수, 전체연봉등수
FROM EMP
WHERE 부서별로 연봉등수가 1등부터 2등;

SELECT T.*
FROM
(
    SELECT ENAME "사원명", DEPTNO "부서번호", (SAL*12+NVL(COMM, 0)) "연봉"
         , RANK() OVER(PARTITION BY DEPTNO ORDER BY (SAL*12+NVL(COMM, 0)) DESC) "부서내연봉등수"
         , RANK() OVER(ORDER BY (SAL*12+NVL(COMM, 0)) DESC) "전체연봉등수" 
    FROM EMP
) T
WHERE T.부서내연봉등수 <= 2
ORDER BY T.부서번호;
--==>>
/*
KING    10    60000    1    1
CLARK    10    29400    2    6
FORD    20    36000    1    2
SCOTT    20    36000    1    2
BLAKE    30    34200    1    5
ALLEN    30    19500    2    7
*/

SELECT T.*
FROM
(
    SELECT ENAME "사원명", DEPTNO "부서번호", (SAL*12+NVL(COMM, 0)) "연봉"
         , DENSE_RANK() OVER(PARTITION BY DEPTNO ORDER BY (SAL*12+NVL(COMM, 0)) DESC) "부서내연봉등수"
         , DENSE_RANK() OVER(ORDER BY (SAL*12+NVL(COMM, 0)) DESC) "전체연봉등수" 
    FROM EMP
) T
WHERE T.부서내연봉등수 <= 2
ORDER BY T.부서번호;
--==>>
/*
KING    10    60000    1    1
CLARK    10    29400    2    5
FORD    20    36000    1    2
SCOTT    20    36000    1    2
JONES    20    35700    2    3
BLAKE    30    34200    1    4
ALLEN    30    19500    2    6
*/