Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Archives
Today
Total
관리 메뉴

Everything has an expiration date

[Oracle] 20231026 [프로그램소스] - 231026_01_SCOTT, 231026_02_HR, 231026_03_SCOTT 본문

[Oracle]/SQL (Program source)

[Oracle] 20231026 [프로그램소스] - 231026_01_SCOTT, 231026_02_HR, 231026_03_SCOTT

Jelly-fish 2023. 10. 26. 17:48



20231026_01_SCOTT.SQL

-- [서브상단쿼리 내부 케이스문 실험]
--************************************************************************

SELECT ENAME, (SELECT CASE WHEN HIREDATE > E.HIREDATE
                     THEN '라라'
                     WHEN HIREDATE = E.HIREDATE
                     THEN '루루'
                     ELSE '하하'
                END
                FROM EMP
                WHERE ENAME = E.ENAME) -- 단일 값이 될 수 있도록 WHERE 절을 이용해야 한다.
                
FROM EMP E;


SELECT TO_CHAR(HIREDATE, 'YYYY-MM')
FROM EMP;


SELECT CASE WHEN TO_CHAR(HIREDATE, 'YYYY-MM') = '1980-12'
            THEN '왓핫핫'
            WHEN TO_CHAR(HIREDATE, 'YYYY-MM') = '1981-02'
            THEN '유후'
            ELSE '루라라'
        END "TEST"
FROM EMP;



SELECT ENAME
FROM EMP;

SELECT CASE WHEN TO_CHAR(HIREDATE, 'YYYY-MM') = '1980-12'
                     THEN '라라'
                     WHEN TO_CHAR(HIREDATE, 'YYYY-MM') = '1981-02'
                     THEN '루루'
                     ELSE '하하'
                END
         FROM EMP;
--************************************************************************

SELECT USER
FROM DUAL;
--==>> SCOTT


-- 지난시간 복습

--○ EMP 테이블과 DEPT 테이블을 대상으로
--   직종이 MANAGER 와 CLERK 인 사원들만
--   부서번호, 부서명, 사원명, 직종명, 급여 항목을 조회한다.


SELECT *
FROM EMP;

SELECT *
FROM DEPT;


SELECT E.DEPTNO "부서번호", D.DNAME "부서명", E.ENAME "사원명"
     , E.JOB "직종명", E.SAL "급여"
FROM EMP E
     FULL OUTER JOIN 
     DEPT D
     ON
     E.DEPTNO = D.DEPTNO
WHERE E.JOB IN ('MANAGER', 'CLERK');


SELECT E.DEPTNO, D.DNAME, E.ENAME, E.JOB, E.SAL
FROM TBL_EMP E 
LEFT JOIN 
TBL_DEPT D 
ON E.DEPTNO = D.DEPTNO
WHERE E.JOB = 'MANAGER'
   OR E.JOB = 'CLERK';
   
   
   
-- 부서번호, 부서명, 사원명, 직종명, 급여
-- DEPTNO    DNAME  ENAME    JOB   SAL
-- E, D      D      E        E     E


SELECT 부서번호, 부서명, 사원명, 직종명, 급여
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO;




SELECT DEPTNO, DNAME, ENAME, JOB, SAL
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO;
--==>> 에러 발생
--     (ORA-00904: "DENAME": invalid identifier)
-->    두 테이블 간 중복되는 컬럼에 대한
--     소속 테이블을 정해줘야(명시해줘야) 한다.

--     DEPTNO 가 두 테이블 모두 존재하는 COLUMN 이므로 
--     어떤 테이블에서 가져와야 하는지 알 수 없다.



-- 양쪽에 모두 존재하는 컬럼을 꺼내쓸 때는, 부모 테이블의 컬럼을 꺼내 써야 한다.
-- 부모 테이블? - 어떤 테이블이 부모 테이블이고, 어떤 테이블이 자식 테이블일까?
-- 연결고리 컬럼 DEPTNO 컬럼을 봤을 때... 
-- DEPT 컬럼에는 10, 20, 30, 40 이 하나씩이지만
-- EMP 에는 10이 여러 개, 20이 여러 개... 
-- 즉, 하나의 부모에 여러 자식이 있으므로 DEPT 테이블이 부모가 되는 것이다.

--==>> 에러 발생
--     (ORA-00918: column ambiguously defined)
-->    두 테이블 간 중복되는 컬럼에 대한
--     소속 테이블을 정해줘야(명시해줘야) 한다.

--     DEPTNO 가 두 테이블 모두 존재하는 COLUMN 이므로 
--     어떤 테이블에서 가져와야 하는지 알 수 없다.
--****************************************************************
-- → DNAME 이라는 컬럼은 DEPT 테이블에만 존재하므로
--    테이블 별칭 ALIAS 를 따로 명시해 주지 않아도 괜찮지만
--    DEPTNO의 경우, EMP, DEPT 테이블에 모두 있는 컬럼이다 보니까
--    두 테이블 중 어떤 테이블에서 가져와야 하는지를 오라클이 알 수 없으므로
--    오류가 발생한 것이다.

-- ※ [총정리] ------------------------------------------------------------------
-- 따라서 양쪽에 겹치는 컬럼이 존재할 경우
-- 소속 테이블을 명시해 주어야 오류가 발생하지 않는다.
--------------------------------------------------------------------------------


-- 이때 소속 테이블을 명시할 경우, 부모 테이블로 사용해야 한다.


-- 두 개의 관계에서, DEPTNO 가 하나인 경우 = 부모
--                  DEPTNO 가 여러 개 인 경우 = 자식

SELECT D.DEPTNO, DNAME, ENAME, JOB, SAL
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO;





-- ※ 두 테이블 간 중복되는 컬럼에 대해 소속 테이블을 명시하는 경우
--   부모 테이블의 컬럼을 참조할 수 있도록 처리해야 한다.


SELECT *
FROM EMP;   -- 자식테이블 (DEPTNO 의 값이 여러 개임.) → 자식



SELECT *
FROM DEPT;  -- 부모 테이블 (DEPTNO 의 값이 단일 값임.) → 부모



SELECT D.DEPTNO, DNAME, ENAME, JOB, SAL
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO;




--★★  두 테이블에 모두 포함되어 있는 중복된 컬럼이 아니더라도
--      컬럼의 소속 테이블을 명시해 줄 수 있기를 권장한다.


-- 중복된 컬럼이 아니더라도 모두 테이블의 ALIAS를 앞에 붙여주었다.
SELECT D.DEPTNO, D.DNAME, E.ENAME, E.JOB, E.SAL
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO;

--[왜? 컬럼의 소속 테이블을 명시해 주어야 하나?]

-- 처음에 컬럼을 발견하자마자 바로 불러왔다면 오류가 발생하지않았을 것이다
-- 별칭을 정해주지 않으면 FROM 에 속한 모든 테이블을 조회한 후에 컬럼을 가져오기 때문이다.
-- 즉, 별칭을 정하지 않으면 EMP, DEPT 테이블을 모두 조회해 보고 컬럼이 존재하는 테이블에서 가져오기 때문에
-- 별칭을 명시해주게 되면 테이블의 별칭과 일치하는 테이블만 조회하므로 양쪽 다 둘러보지 않는다.
-- 업무 지시가 명확해지는 것이다.
-- 즉, 모든 테이블을 조회하지 않고 명시해 준 ALIAS에 속하는 테이블만 조회하므로
-- 리소스가 감소한다.

-- 데이터 양이 많아지게 되면, ALIAS나 테이블명을 붙여주지 않은 쿼리문을 수행할 때
-- 딜레이가 더욱 발생할 수 있다.







-- [왜? 양쪽 테이블에서 중복 컬럼이 있을 경우 부모 테이블에서 가져와야 하는가]
-- 자식 것에서 따온 후에 OUTER JOIN을 하게 되면... 
-- 부모 테이블에 있는 값이더라도 DEPTNO = 40
-- 자식 것에 40이 포함되어 있지 않으면 DEPTNO 가 40인 항목이 NULL 로 나온다.


SELECT E.DEPTNO, D.DNAME, E.ENAME, E.JOB, E.SAL
FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO;
--==>>
/*
10	    ACCOUNTING	    CLARK	MANAGER	    2450
10	    ACCOUNTING	    KING    	PRESIDENT	5000
10	    ACCOUNTING	    MILLER	CLERK	    1300
20	    RESEARCH	        JONES	MANAGER	    2975
20	    RESEARCH	        FORD	ANALYST	3000
20	    RESEARCH	        ADAMS	CLERK	1100
20	    RESEARCH	        SMITH	CLERK	800
20   	RESEARCH	        SCOTT	ANALYST	3000
30	    SALES	        WARD	SALESMAN	1250
30	    SALES	        TURNER	SALESMAN	1500
30	    SALES	        ALLEN	SALESMAN	1600
30	    SALES	        JAMES	CLERK	950
30	    SALES	        BLAKE	MANAGER	2850
30	    SALES	        MARTIN	SALESMAN	1250
(null) 	OPERATIONS                              ← CHECK~!!! (E.DEPTNO)
                                                   자식 테이블 EMP 로 DEPTNO를 가져오자
                                                   E.DEPTNO 부서번호가 NULL인것을 확인!!
*/






SELECT D.DEPTNO, D.DNAME, E.ENAME, E.JOB, E.SAL
FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO;
--==>>
/*
10	    ACCOUNTING	    CLARK	MANAGER	    2450
10	    ACCOUNTING	    KING    	PRESIDENT	5000
10	    ACCOUNTING	    MILLER	CLERK	    1300
20	    RESEARCH	        JONES	MANAGER	    2975
20	    RESEARCH	        FORD	ANALYST	3000
20	    RESEARCH	        ADAMS	CLERK	1100
20	    RESEARCH	        SMITH	CLERK	800
20   	RESEARCH	        SCOTT	ANALYST	3000
30	    SALES	        WARD	SALESMAN	1250
30	    SALES	        TURNER	SALESMAN	1500
30	    SALES	        ALLEN	SALESMAN	1600
30	    SALES	        JAMES	CLERK	950
30	    SALES	        BLAKE	MANAGER	2850
30	    SALES	        MARTIN	SALESMAN	1250
40   	OPERATIONS                              ← CHECK~!!! (D.DEPTNO)
                                                   부모 테이블 DEPT 로 DEPTNO를 가져오자
                                                   D.DEPTNO 부서번호가 40으로 적용된 것을 확인!!
*/


SELECT *
FROM EMP;

--○ SELF JOIN (자기 조인)


-- EMP 테이블의 데이터를 다음과 같이 조회할 수 있도록 쿼리문을 구성한다.
/*
-------------------------------------------------------------------------
  사원번호     사원명     직종명     관리자번호  관리자명     관리자직종명
-------------------------------------------------------------------------
    7369      SMITH      CLERK       7902       FORD          ANALYST       
*/


SELECT E3.EMPNO "사원번호"
     , E3.ENAME "사원명"
     , E3.JOB "직종명"
     , MT.EMPNO "관리자번호"
     , MT.ENAME "관리자명"
     , MT.JOB "관리자직종명"
FROM
EMP E3
FULL OUTER JOIN
( 
    SELECT E2.EMPNO "EMPNO"
         , E2.ENAME "ENAME"
         , E2.JOB   "JOB"
    FROM EMP E2
    WHERE E2. EMPNO
    IN
    (
        SELECT E.MGR
        FROM
        (
            SELECT EMPNO "사원번호"
                 , ENAME "사원명"
                 , JOB "직종명"
                 , MGR "관리자번호"
            FROM EMP
        ) T
        INNER JOIN
        EMP E
        ON E.EMPNO = T.사원번호
        WHERE E.MGR = T.관리자번호
    )
) MT
ON E3.MGR = MT.EMPNO
ORDER BY 사원번호 ASC;






SELECT E3.EMPNO "사원번호"
     , E3.ENAME "사원명"
     , E3.JOB "직종명"
     , MT.EMPNO "관리자번호"
     , MT.ENAME "관리자명"
     , MT.JOB "관리자직종명"
FROM
EMP E3                      -- 일반 EMP 테이블 (모든 사원 추출 용도)
FULL OUTER JOIN
( 
    SELECT E2.EMPNO "EMPNO"
         , E2.ENAME "ENAME"
         , E2.JOB   "JOB"
    FROM EMP E2
    WHERE E2. EMPNO
    IN
    (
        SELECT E.MGR
        FROM EMP E
    )
) MT                        -- 매니저 테이블 (매니저에 해당하는 사원 추출 용도)
ON E3.MGR = MT.EMPNO
ORDER BY 사원번호 ASC;




SELECT ENAME
FROM EMP
WHERE ENAME LIKE TO_CHAR('S' + 'MITH');


SELECT CHAR('S' + 'MITH')
FROM DUAL;















-- EMP 테이블의 데이터를 다음과 같이 조회할 수 있도록 쿼리문을 구성한다.
/*
총 2개의 테이블이 필요하다.

-------------------------------------------------------------------------
  사원번호     사원명     직종명     관리자번호  관리자명     관리자직종명
  EMPNO        ENAME      JOB          MGR
  
                                     EMPNO       ENAME        JOB
-------------------------------------------------------------------------
    7369      SMITH      CLERK       7902       FORD          ANALYST  
 ---------------------------------------- E1
                                     -------------------------------- E2
*/


SELECT 사원번호 사원명 직종명 관리자번호 관리자명 관리자직종명
FROM EMP;

SELECT EMPNO "사원번호", ENAME "사원명", JOB "직종명", MGR "관리자번호"
      , EMPNO "관리자번호" , ENAME "관리자명", JOB "관리자직종명"
FROM EMP;



SELECT  E1.EMPNO "사원번호", E1.ENAME "사원명", E1.JOB "직종명", E1.MGR "관리자번호"
      , E2.EMPNO "관리자번호", E2.ENAME "관리자명", E2.JOB "관리자직종명"    -- 관리자
FROM EMP E1 JOIN EMP E2
ON E1.MGR = E2.EMPNO;
-- KING 이 빠져 있으므로 OUTER 조인을 사용해야 한다.



SELECT  E1.EMPNO "사원번호", E1.ENAME "사원명", E1.JOB "직종명", E1.MGR "관리자번호"
      , E2.EMPNO "관리자번호", E2.ENAME "관리자명", E2.JOB "관리자직종명"    -- 관리자
FROM EMP E1 LEFT JOIN EMP E2
ON E1.MGR = E2.EMPNO;
-- KING이 포함되어 있다!



-- 92 코드로 변경
-- LEFT 조인 삭제 -> CROSS 조인으로 변경 (92)
-- 조건식의 E2.EMPNO(+) 구성.
SELECT  E1.EMPNO "사원번호", E1.ENAME "사원명", E1.JOB "직종명", E1.MGR "관리자번호"
      , E2.EMPNO "관리자번호", E2.ENAME "관리자명", E2.JOB "관리자직종명"    -- 관리자
FROM EMP E1, EMP E2
WHERE E1.MGR = E2.EMPNO(+);

 



 
 
20231026_02_HR.SQL

SELECT USER
FROM DUAL;
--==>> HR
-- ID : HR, PW : LION
-- ID : SCOTT, PW : TIGER

--○ 세 개 이상의 테이블 조인(JOIN, 결합)

-- 형식 1. (SQL 1992 CODE)

SELECT 테이블명1.컬럼명, 테이블명2.컬럼명, 테이블명3.컬럼명
FROM 테이블명1, 테이블명2, 테이블명3
WHERE 테이블명1.컬럼명1 = 테이블명2.컬럼명1
  AND 테이블명2.컬럼명2 = 테이블명3.컬럼명2;



-- 형식 2. (SQL 1999 CODE)

SELECT 테이블명1.컬럼명, 테이블명2.컬럼명, 테이블명3.컬럼명
FROM 테이블명1 JOIN 테이블명2
ON 테이블명1.컬럼명1 = 테이블명2.컬럼명1      -- ① 테이블1, 테이블2를 먼저 결합
   JOIN 테이블명3                            -- ② 결합된 결과에 또다른 테이블3 결합
   ON 테이블명2.컬럼명2 = 테이블명3.컬럼명2;



--○ HR 계정 소유의 테이블 또는 뷰 목록 조회

SELECT *
FROM TAB;
--==>>
/*
COUNTRIES	        TABLE	
DEPARTMENTS	        TABLE	
EMPLOYEES	        TABLE	
EMP_DETAILS_VIEW    	VIEW	
JOBS	                TABLE	
JOB_HISTORY	        TABLE	
LOCATIONS	        TABLE	
REGIONS	            TABLE	
*/


--○ HR.JOBS, HR.EMPLOYEES, HR.DEPARTMENTS 테이블을 대상으로
--   직원들의 데이터를
--   FIRST_NAME, LAST_NAME, JOB_TITLE, DEPARTMENT_NAME 항목으로 조회한다.



-- JOBS : JOB_ID	  JOB_TITLE  MIN_SALARY	 MAX_SALARY

-- EMPLOYEES : EMPLOYEE_ID	FIRST_NAME	LAST_NAME	EMAIL	
--  PHONE_NUMBER	HIRE_DATE	JOB_ID	SALARY	COMMISSION_PCT	MANAGER_ID	DEPARTMENT_ID

-- DEPARTMENTS : DEPARTMENT_ID	DEPARTMENT_NAME	MANAGER_ID	LOCATION_ID


-- FULL OUTER JOIN
SELECT E.FIRST_NAME, E.LAST_NAME, J.JOB_TITLE, D.DEPARTMENT_NAME
FROM JOBS J
     INNER JOIN
     EMPLOYEES E
     ON J.JOB_ID = E.JOB_ID
     FULL OUTER JOIN                            -- 전체를 OUTER JOIN 한 후에
     DEPARTMENTS D                              
     ON E.DEPARTMENT_ID = D.DEPARTMENT_ID
WHERE E.FIRST_NAME IS NOT NULL;                 -- 이름이 NULL 이 아닌 사원만 조회.


-- LEFT OUTER 
SELECT E.FIRST_NAME, E.LAST_NAME, J.JOB_TITLE, D.DEPARTMENT_NAME
FROM JOBS J
     INNER JOIN
     EMPLOYEES E
     ON J.JOB_ID = E.JOB_ID
     LEFT OUTER JOIN                -- EMPLOYEES 테이블의 전체 요소가 출력될 수 있도록 
                                    -- LEFT OUTER JOIN 으로 구성.
     DEPARTMENTS D
     ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;




-- [선생님 풀이]
--○ HR.JOBS, HR.EMPLOYEES, HR.DEPARTMENTS 테이블을 대상으로
--   직원들의 데이터를
--   FIRST_NAME, LAST_NAME, JOB_TITLE, DEPARTMENT_NAME 항목으로 조회한다.
--        E         E          J             D
 
-- 부서에 대한 정보
SELECT *
FROM DEPARTMENTS;
--↑
--◎ 관계 컬럼 : DEPARTMENT_ID   → 관계 컬럼
--↓

-- 사원에 대한 정보
-- 직종의 ID가 들어 감.
SELECT *
FROM EMPLOYEES;
--↑
--◎ 관계 컬럼 : JOB_ID   → 관계 컬럼
--↓

-- 직종 ID별
-- 직종의 이름이 들어 감.
SELECT *
FROM JOBS;




SELECT E.FIRST_NAME, E.LAST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;



-- 레코드의 개수 확인.
SELECT COUNT(*)
FROM EMPLOYEES;
--==>> 107

SELECT COUNT(*)
FROM EMPLOYEES E JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
--==>> 106
--> 연결되지 못한 하나가 제외되었음을 확인할 수 있다!!

SELECT *
FROM EMPLOYEES;
--==>>
/*
DEPARTMENT_ID가 (null)이어서 제외됨.
178	Kimberely	Grant	KGRANT	011.44.1644.429263	2007-05-24	SA_REP	7000	0.15	149	 (null)
*/


-- 모든 사원을 반영할 수 있도록 
-- LEFT OUTER JOIN 을 사용.
SELECT COUNT(*)
FROM EMPLOYEES E LEFT OUTER JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
--==>> 107
--> LEFT OUTER JOIN 을 하자 Kimberely 가 제대로 반영되었음을 확인할 수 있다.




SELECT  E.FIRST_NAME, E.LAST_NAME, J.JOB_TITLE, D.DEPARTMENT_NAME
FROM EMPLOYEES E LEFT OUTER JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID
   JOIN JOBS J
   ON E.JOB_ID = J.JOB_ID;



-- 연결고리 컬럼 안의 값이 NULL 일 때 데이터가 제외되므로 이를 주의하여 관찰하고
-- 제외되는 대상이 있는지 COUNT(*) 함수를 사용하여 확인한 후에 
-- INNER JOIN 을 써야할지, OUTER JOIN 을 써야할지 결정해야 한다.









--○ EMPLOYEES, DEPARTMENTS, JOBS, LOCATIONS, COUNTRIES, REGIONS 테이블을 대상으로

--   직원들의 데이터를 다음과 같이 조회한다.
--   FIRST_NAME, LAST_NAME, JOB_TITLE, DEPARTMENT_NAME, CITY, COUNTRY_NAME, REGION_NAME


-- [테이블별 컬럼]===============================================================

-- JOBS : JOB_ID	  JOB_TITLE  MIN_SALARY	 MAX_SALARY

-- EMPLOYEES : EMPLOYEE_ID	FIRST_NAME	LAST_NAME	EMAIL	
--             PHONE_NUMBER	HIRE_DATE	JOB_ID	SALARY	COMMISSION_PCT	
--             MANAGER_ID	DEPARTMENT_ID

-- DEPARTMENTS : DEPARTMENT_ID	DEPARTMENT_NAME	MANAGER_ID	LOCATION_ID

-- LOCATIONS   : LOCATION_ID	  STREET_ADDRESS	  POSTAL_CODE	 CITY	
--               STATE_PROVINCE 	COUNTRY_ID


-- COUNTRIES   : COUNTRY_ID	COUNTRY_NAME   REGION_ID

-- REGIONS : REGION_ID	REGION_NAME

--==============================================================================




--   FIRST_NAME, LAST_NAME, JOB_TITLE, DEPARTMENT_NAME, CITY, COUNTRY_NAME, REGION_NAME
--       E          E           J           D           L       C           R


-- 99 CODE!! - FULL OUTER JOIN 사용 후, WHERE 조건 걸기.
SELECT E.FIRST_NAME, E.LAST_NAME, J.JOB_TITLE, D.DEPARTMENT_NAME
     , L.CITY, C.COUNTRY_NAME, R.REGION_NAME
FROM EMPLOYEES E
     FULL OUTER JOIN
     JOBS J
     ON E.JOB_ID = J.JOB_ID
        FULL OUTER JOIN
        DEPARTMENTS D
        ON E.DEPARTMENT_ID = D.DEPARTMENT_ID
           FULL OUTER JOIN
           LOCATIONS L
           ON D.LOCATION_ID = L.LOCATION_ID
              FULL OUTER JOIN
              COUNTRIES C
              ON L.COUNTRY_ID = C.COUNTRY_ID
                 FULL OUTER JOIN
                 REGIONS R
                 ON C.REGION_ID = R.REGION_ID
WHERE E.FIRST_NAME IS NOT NULL;



-- 99 CODE!! - 모두 LEFT OUTER JOIN 사용.
SELECT E.FIRST_NAME, E.LAST_NAME, J.JOB_TITLE, D.DEPARTMENT_NAME
     , L.CITY, C.COUNTRY_NAME, R.REGION_NAME
FROM EMPLOYEES E
     LEFT OUTER JOIN
     JOBS J
     ON E.JOB_ID = J.JOB_ID
        LEFT OUTER JOIN
        DEPARTMENTS D
        ON E.DEPARTMENT_ID = D.DEPARTMENT_ID
           LEFT OUTER JOIN
           LOCATIONS L
           ON D.LOCATION_ID = L.LOCATION_ID
              LEFT OUTER JOIN
              COUNTRIES C
              ON L.COUNTRY_ID = C.COUNTRY_ID
                 LEFT OUTER JOIN
                 REGIONS R
                 ON C.REGION_ID = R.REGION_ID
WHERE E.FIRST_NAME IS NOT NULL;


-- 92 CODE!!
SELECT E.FIRST_NAME, E.LAST_NAME, J.JOB_TITLE, D.DEPARTMENT_NAME
     , L.CITY, C.COUNTRY_NAME, R.REGION_NAME
FROM EMPLOYEES E, JOBS J, DEPARTMENTS D, LOCATIONS L, COUNTRIES C, REGIONS R
WHERE E.JOB_ID = J.JOB_ID(+)
      AND
      E.DEPARTMENT_ID = D.DEPARTMENT_ID(+)
      AND
      D.LOCATION_ID = L.LOCATION_ID(+)
      AND
      L.COUNTRY_ID = C.COUNTRY_ID(+)
      AND
      C.REGION_ID = R.REGION_ID(+);
      


-- FIRST_NAME, LAST_NAME, JOB_TITLE, DEPARTMENT_NAME, CITY, COUNTRY_NAME, REGION_NAME

 




 
 
 
20231026_03_SCOTT.SQL
 

SELECT USER
FROM DUAL;
--==>> SCOTT


---------------------------------------------------
-- JOIN 을 통해 테이블을 결합시키게 되면
-- A 테이블 B 테이블 (조건에 맞게끔 연결시킨다.)
-- 좌우로 합치는 것이다.

-- 합집합  UNION
-- UNION 은 길게 세로로 합치는 것
---------------------------------------------------


--■■■ UNION / UNION ALL ■■■--

--○ 실습 테이블 생성(테이블명 : TBL_JUMUN)

CREATE TABLE TBL_JUMUN               -- 주문 테이블 생성
( JUNO      NUMBER                   -- 주문 번호
, JECODE    VARCHAR2(30)             -- 제품 코드
, JUSU      NUMBER                   -- 주문 수량
, JUDAY     DATE    DEFAULT SYSDATE  -- 주문 일자
);
--==>> Table TBL_JUMUN이(가) 생성되었습니다.
-- 고객의 주문이 발생(접수)되었을 경우
-- 주문 내용에 대한 데이터가 입력될 수 있도록 처리하는 테이블



-- 실습 진행 간 제품 코드(JECODE) 에는
-- 편의상 제품의 코드를 참조한다고 가정하고 제품의 이름을 입력한다.


--○ 데이터 입력 → 고객의 주문 발생(접수)
INSERT INTO TBL_JUMUN
VALUES(1, '포스틱', 20, TO_DATE('2001-11-01 09:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(2, '빅파이', 10, TO_DATE('2001-11-01 10:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(3, '사또밥', 30, TO_DATE('2001-11-01 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(4, '포카칩', 20, TO_DATE('2001-11-02 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(5, '포카칩', 30, TO_DATE('2001-11-03 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(6, '빅파이', 20, TO_DATE('2001-11-04 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(7, '홈런볼', 10, TO_DATE('2001-11-05 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(8, '홈런볼', 10, TO_DATE('2001-11-06 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(9, '오예스', 20, TO_DATE('2001-11-07 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(10, '사또밥', 10, TO_DATE('2001-11-08 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(11, '빼빼로', 20, TO_DATE('2001-11-09 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(12, '감자깡', 10, TO_DATE('2001-11-10 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(13, '빼빼로', 20, TO_DATE('2001-11-11 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(14, '홈런볼', 20, TO_DATE('2001-11-12 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(15, '포카칩', 10, TO_DATE('2001-11-13 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(16, '포카칩', 20, TO_DATE('2001-11-16 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(17, '마이쮸', 20, TO_DATE('2001-11-17 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(18, '맛동산', 30, TO_DATE('2001-11-18 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(19, '맛동산', 20, TO_DATE('2001-11-19 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN
VALUES(20, '꼬북칩', 30, TO_DATE('2001-11-20 11:10:10', 'YYYY-MM-DD HH24:MI:SS'));
--==>> 1 행 이(가) 삽입되었습니다. * 20


--○ 확인
SELECT *
FROM TBL_JUMUN; 
--==>>
/*
JUNO	    JECODE	JUSU	    JUDAY
1	    포스틱	20	2001-11-01 
2	    빅파이	10	2001-11-01 
3	    사또밥	30	2001-11-01 
4	    포카칩	20	2001-11-02 
5	    포카칩	30	2001-11-03 
6	    빅파이	20	2001-11-04 
7	    홈런볼	10	2001-11-05 
8	    홈런볼	10	2001-11-06 
9	    오예스	20	2001-11-07 
10	    사또밥	10	2001-11-08 
11	    빼빼로	20	2001-11-09 
12	    감자깡	10	2001-11-10 
13	    빼빼로	20	2001-11-11 
14	    홈런볼	20	2001-11-12 
15	    포카칩	10	2001-11-13 
16	    포카칩	20	2001-11-16 
17	    마이쮸	20	2001-11-17 
18	    맛동산	30	2001-11-18 
19	    맛동산	20	2001-11-19 
20	    꼬북칩	30	2001-11-20 
*/

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


-- ALTER SESSION SET을 테이블 COMMIT 이전에 하게 되면
-- AUTO COMMIT(자동커밋)이 되어버리므로 항상 유의하자.

--○ 날짜에 대한 세션 설정 변경
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

--○ 확인
SELECT *
FROM TBL_JUMUN; 
--==>>
/*
JUNO	    JECODE	JUSU	    JUDAY
1	    포스틱	20	2001-11-01 09:10:10
2	    빅파이	10	2001-11-01 10:10:10
3	    사또밥	30	2001-11-01 11:10:10
4	    포카칩	20	2001-11-02 11:10:10
5	    포카칩	30	2001-11-03 11:10:10
6	    빅파이	20	2001-11-04 11:10:10
7	    홈런볼	10	2001-11-05 11:10:10
8	    홈런볼	10	2001-11-06 11:10:10
9	    오예스	20	2001-11-07 11:10:10
10	    사또밥	10	2001-11-08 11:10:10
11	    빼빼로	20	2001-11-09 11:10:10
12	    감자깡	10	2001-11-10 11:10:10
13	    빼빼로	20	2001-11-11 11:10:10
14	    홈런볼	20	2001-11-12 11:10:10
15	    포카칩	10	2001-11-13 11:10:10
16	    포카칩	20	2001-11-16 11:10:10
17	    마이쮸	20	2001-11-17 11:10:10
18	    맛동산	30	2001-11-18 11:10:10
19	    맛동산	20	2001-11-19 11:10:10
20	    꼬북칩	30	2001-11-20 11:10:10
*/

--○ 추가 데이터 입력 → 2001년 부터 시작된 주문이 현재(2023년)까지 계속 발생~!!! 진행중~!!!
-- 과자 사업 하는 현욱이가 장사가 잘 되구 있다


INSERT INTO TBL_JUMUN VALUES(98764, '꼬북칩', 10, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(98765, '빼빼로', 30, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(98766, '빼빼로', 20, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(98767, '에이스', 40, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(98768, '홈런볼', 10, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(98769, '감자깡', 20, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(98770, '맛동산', 10, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(98771, '웨하스', 20, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(98772, '맛동산', 30, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(98773, '오레오', 20, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(98774, '빼빼로', 50, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(98775, '오감자', 10, SYSDATE);
--==>> 1 행 이(가) 삽입되었습니다.


--○ 확인
SELECT *
FROM TBL_JUMUN;
--==>>
/*
   1	포스틱	20	2001-11-01 09:10:10
   2 	빅파이	10	2001-11-01 10:10:10
   3	사또밥	30	2001-11-01 11:10:10
   4	포카칩	20	2001-11-02 11:10:10
   5	포카칩	30	2001-11-03 11:10:10
   6	빅파이	20	2001-11-04 11:10:10
   7	홈런볼	10	2001-11-05 11:10:10
   8	홈런볼	10	2001-11-06 11:10:10
   9	오예스	20	2001-11-07 11:10:10
   10	사또밥	10	2001-11-08 11:10:10
   11	빼빼로	20	2001-11-09 11:10:10
   12	감자깡	10	2001-11-10 11:10:10
   13	빼빼로	20	2001-11-11 11:10:10
   14	홈런볼	20	2001-11-12 11:10:10
   15	포카칩	10	2001-11-13 11:10:10
   16	포카칩	20	2001-11-16 11:10:10
   17	마이쮸	20	2001-11-17 11:10:10
   18	맛동산	30	2001-11-18 11:10:10
   19	맛동산	20	2001-11-19 11:10:10
   20	꼬북칩	30	2001-11-20 11:10:10
98764	꼬북칩	10	2023-10-26 12:46:10
98765	빼빼로	30	2023-10-26 12:46:58
98766	빼빼로	20	2023-10-26 12:47:25
98767	에이스	40	2023-10-26 12:47:53
98768	홈런볼	10	2023-10-26 12:48:16
98769	감자깡	20	2023-10-26 12:48:38
98770	맛동산	10	2023-10-26 12:49:03
98771	웨하스	20	2023-10-26 12:49:25
98772	맛동산	30	2023-10-26 12:49:45
98773	오레오	20	2023-10-26 12:50:08
98774	빼빼로	50	2023-10-26 12:50:29
98775	오감자	10	2023-10-26 12:50:54
*/


--※ 현욱이가 과자 쇼핑몰 운영 중...
--   TBL_JUMIN 테이블이 무거워진 상황


--◎ 부가 설명
--◎ [테이블이 무거워졌다?]*********************************************************

-- 부서 테이블의 경우 : 꾸준히 계속 늘어나진 않는다.
-- 마트에서 판매하는 물품들의 가짓수 : 상당히 많다. 5만 가지 정도...
-- 새로운 물건이 들어왔을 때, 5만 2천 건...
-- 마트에서 더 이상 취급하지 말자, 4만 7천 건... 상당히 변동적이다.
-- 대략 5만 건의 물품을 다루는데, 데이터의 수량이 변화한다.
-- 그럼에도 유지된다.

-- 한 해 지날 때마다, 회사 사원들의 수가 1000건 이상 증가하지 않는다.


-- 하지만 쇼핑몰의 주문 테이블의 경우
-- 사용자가 주문이 발생할 때마다 계속해서 데이터의 INSERT가 일어나는 테이블이다.
-- → 즉, 회사 사원 테이블, 부서 테이블, 물품 테이블처럼 
--    일정 수준의 데이터량에서 예상 가능한 변동을 일으키는 테이블이 아니다.

-- 하나의 테이블 내부에 데이터가 꽉 찼을 경우, 다른 테이블에 넣으라는 식으로 프로그램 구성 불가능하다.
-- 이렇게 구성하려면 프로그램을 아예 다 뜯어 고쳐야 한다. 
-- 즉, 새로운 테이블을 생성해서 데이터가 저장되는 공간을 새로운 테이블로 저장되도록 진행할 수 없다.
-- A 테이블이 차면 B 테이블에 넣어 → (Ⅹ) 불가능!


-- 쌓인 데이터들을 전부 지워버린다? -(Ⅹ)  하 면 안 돼
-- 예를 들어... 반품이 들어왔다면?
-- 이전에 발송했던 주문내역들을 모두 지워놓은 상황이라면 이것을 확인할 수가 없어진다.
-- 이것을 삭제했는데, 국세청에서 확인을 나왔다면? -> 안 된다!


-- 꽉 찬 테이블의 일부를 다른 곳에 백업시키고 그 만큼을 비워준다.
-- 그렇게 되면 빈 공간에 새로운 데이터들을 담을 수가 있다!! (○)

-- TBL_JUMUN 의 데이터들을 다른 곳에 이관시키도록 처리하자! 

-- 2002년의 주문 내역들을 잘라내서 다른 테이블에 옮겨 담으면 되겠다!

--******************************************************************************



--※ 현욱이가 과자 쇼핑몰 운영 중...
--   TBL_JUMIN 테이블이 무거워진 상황

-- 어플리케이션과의 연동으로 인해 주문 내역을
-- 앞으로는 다른 테이블에 저장될 수 있도록 만드는 것은 거의 불가능한 상황.
-- 기존의 모든 데이터를 덮어놓고 지우는 것도 불가능한 상황.
-- → 결과적으로...
--    현재까지 누적된 주문 데이터 중
--    금일 발생한 주문 내역을 제외하고
--    나머지 데이터를 다른 테이블(TBL_JUMUNBACKUP)로
--    데이터를 이관하여 백업을 수행할 계획


-- TBL_JUMUN 안에 오늘 주문한 내역이 아닌 것들을 저장해 보자.



-- 값 확인

SELECT *
FROM TBL_JUMUN;


-- 테이블 생성 (TBL_JUMUNBACKUP)






-- 오늘 날짜가 아닌 데이터들만 조회하도록 변경.
SELECT TO_CHAR(JUDAY, 'YYYY-MM-DD')
FROM TBL_JUMUN
WHERE TO_CHAR(JUDAY, 'YYYY-MM-DD') != TO_CHAR(SYSDATE, 'YYYY-MM-DD');




-- 이것을 백업 테이블에 저장..
CREATE TABLE TBL_JUMUNBACKUP  
AS
SELECT *
FROM TBL_JUMUN
WHERE TO_CHAR(JUDAY, 'YYYY-MM-DD') != TO_CHAR(SYSDATE, 'YYYY-MM-DD');


SELECT *
FROM TBL_JUMUNBACKUP;
-------------------------------------------------------------------------------

-- 테이블 복사 (JUMUN 테이블)
CREATE TABLE TBL_JUMUN_TEST_TABLE 
AS
SELECT *
FROM TBL_JUMUN;


-- 이전 날짜 테이블에서 삭제하기.
DELETE
FROM TBL_JUMUN_TEST_TABLE
WHERE TO_CHAR(JUDAY, 'YYYY-MM-DD') != TO_CHAR(SYSDATE, 'YYYY-MM-DD');

-- 확인 (오늘 날짜만 남아있음)
SELECT *
FROM TBL_JUMUN_TEST_TABLE;
/*
98764	꼬북칩	10	2023-10-26 12:46:10
98765	빼빼로	30	2023-10-26 12:46:58
98766	빼빼로	20	2023-10-26 12:47:25
98767	에이스	40	2023-10-26 12:47:53
98768	홈런볼	10	2023-10-26 12:48:16
98769	감자깡	20	2023-10-26 12:48:38
98770	맛동산	10	2023-10-26 12:49:03
98771	웨하스	20	2023-10-26 12:49:25
98772	맛동산	30	2023-10-26 12:49:45
98773	오레오	20	2023-10-26 12:50:08
98774	빼빼로	50	2023-10-26 12:50:29
98775	오감자	10	2023-10-26 12:50:54
*/





CREATE TABLE TBL_JUMUNBACKUP2
AS
SELECT *
FROM 금일발생한주문이아닌것;


SELECT *
FROM TBL_JUMUN
WHERE TO_CHAR(JUDAY, 'YYYY-MM-DD') != TO_CHAR(SYSDATE, 'YYYY-MM-DD');
                                     ---------------------------------
                                          -- '2023-10-26'



CREATE TABLE TBL_JUMUNBACKUP2
AS
SELECT *
FROM TBL_JUMUN
WHERE TO_CHAR(JUDAY, 'YYYY-MM-DD') != TO_CHAR(SYSDATE, 'YYYY-MM-DD');
--==>> Table TBL_JUMUNBACKUP2이(가) 생성되었습니다.


-- 확인
SELECT *
FROM TBL_JUMUNBACKUP2;
--==>>
/*
1	포스틱	20	2001-11-01 09:10:10
2	빅파이	10	2001-11-01 10:10:10
3	사또밥	30	2001-11-01 11:10:10
4	포카칩	20	2001-11-02 11:10:10
5	포카칩	30	2001-11-03 11:10:10
6	빅파이	20	2001-11-04 11:10:10
7	홈런볼	10	2001-11-05 11:10:10
8	홈런볼	10	2001-11-06 11:10:10
9	오예스	20	2001-11-07 11:10:10
10	사또밥	10	2001-11-08 11:10:10
11	빼빼로	20	2001-11-09 11:10:10
12	감자깡	10	2001-11-10 11:10:10
13	빼빼로	20	2001-11-11 11:10:10
14	홈런볼	20	2001-11-12 11:10:10
15	포카칩	10	2001-11-13 11:10:10
16	포카칩	20	2001-11-16 11:10:10
17	마이쮸	20	2001-11-17 11:10:10
18	맛동산	30	2001-11-18 11:10:10
19	맛동산	20	2001-11-19 11:10:10
20	꼬북칩	30	2001-11-20 11:10:10
*/
--> TBL_JUMUN 테이블의 데이터들 중
--  금일 주뭄 내역 이외의 데이터는 모두 TBL_JUMUNBACKUP2 테이블에
--  백업을 마친 상태~!!!


-- TBL_JUMUN 테이블의 데이터들 중
-- 백업을 마친 데이터들... 즉, 금일 발생한 주문 내역이 아닌 데이터들
-- 제거

-- 데이터 확인
SELECT *
FROM TBL_JUMUN;


-- 제거해야 할 데이터 확인

SELECT *
FROM TBL_JUMUN
WHERE TO_CHAR(JUDAY, 'YYYY-MM-DD') != TO_CHAR(SYSDATE, 'YYYY-MM-DD');


-- 제거해야 될 데이터에 문제가 없다면...
-- 이전 날짜 테이블에서 삭제하기.
DELETE
FROM TBL_JUMUN
WHERE TO_CHAR(JUDAY, 'YYYY-MM-DD') != TO_CHAR(SYSDATE, 'YYYY-MM-DD');
--==>> 20개 행 이(가) 삭제되었습니다.



-- 확인 (오늘 날짜만 남아있음)
SELECT *
FROM TBL_JUMUN;



-- 선생님 설명

SELECT *
FROM TBL_JUMUN
WHERE 금일발생한주문이 아닌것;


SELECT *
FROM TBL_JUMUN
WHERE TO_CHAR(JUDAY, 'YYYY-MM-DD') != TO_CHAR(SYSDATE, 'YYYY-MM-DD');


DELETE
FROM TBL_JUMUN
WHERE TO_CHAR(JUDAY, 'YYYY-MM-DD') != TO_CHAR(SYSDATE, 'YYYY-MM-DD');
--==>> 20개 행 이(가) 삭제되었습니다.
--     (→ 93763개 행이 삭제된 상황)


-- 확인
SELECT *
FROM TBL_JUMUN;
--==>>
/*
JUNO	    JECODE	JUSU	    JUDAY
98764	꼬북칩	10	2023-10-26 12:46:10
98765	빼빼로	30	2023-10-26 12:46:58
98766	빼빼로	20	2023-10-26 12:47:25
98767	에이스	40	2023-10-26 12:47:53
98768	홈런볼	10	2023-10-26 12:48:16
98769	감자깡	20	2023-10-26 12:48:38
98770	맛동산	10	2023-10-26 12:49:03
98771	웨하스	20	2023-10-26 12:49:25
98772	맛동산	30	2023-10-26 12:49:45
98773	오레오	20	2023-10-26 12:50:08
98774	빼빼로	50	2023-10-26 12:50:29
98775	오감자	10	2023-10-26 12:50:54
*/

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



--※ 아직 제품 발송이 이루어지지 않은 금일 주문 데이터를 제외하고
--   이전의 모든 주문 데이터들이 삭제된 상황이므로
--   테이블은 행(레코드)의 개수가 줄어들어 매우 가벼워진 상황이다.



-- 그런데, 지금까지 주문받은 내역에 대한 정보를
-- 제품별 총 주문량으로나타내어야 할 상황이 발생하게 되었다.
-- 그렇다면, TBL_JUMUNBACKUP 테이블이ㅡ 레코드(행)와
-- TBL_JUMUN 테이블의 레코드(행)를 모두 합쳐
-- 하나의 테이블을 조회하는 것과 같은 결과를 확인할 수 있도록 
-- 조회가 이루어져야 한다.


-- 이때, 사용할 수 있는 것이 UNION!!


--※ 컬럼과 컬럼의 관계를 고려하여 테이블을 결합하고자 하는 경우
--   JOIN 을 사용하지만
--   레코드와 레코드를 결합하고자 하는 경우
--   UNION / UNION ALL 을 사용할 수 있다.


SELECT *
FROM TBL_JUMUNBACKUP;

SELECT *
FROM TBL_JUMUN;




-- UNION 을 넣자, 두 개의 테이블의 레코드가 합쳐진 것을 확인할 수 있다.

SELECT *
FROM TBL_JUMUNBACKUP
UNION
SELECT *
FROM TBL_JUMUN;

-- ↑
-- UNION 과 UNION ALL 의 차이점을 찾을 수 없다.
-- ↓

SELECT *
FROM TBL_JUMUNBACKUP
UNION ALL
SELECT *
FROM TBL_JUMUN;



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



SELECT *
FROM TBL_JUMUN
UNION
SELECT *
FROM TBL_JUMUNBACKUP;

-- ↑
-- UNION 과 UNION ALL 의 차이점을 찾을 수 없다.
-- ↓

SELECT *
FROM TBL_JUMUN
UNION ALL
SELECT *
FROM TBL_JUMUNBACKUP;


-- UNION
-- UNION ALL 첫 번째 컬럼을 기준으로 해서 오름차순 정렬이 들어간다.


-- TBL_JUMUNBACKUP 을 위에 작성했을 때는 둘의 결과에 차이가 없었지만
-- TBL_JUMUNBACKUP 을 아래에 작성하고 TBL_JUMUN 을 위에 작성하자

-- UNION : 첫 번째 컬럼을 기준으로 해서 오름차순 정렬이 들어간 것을 확인
-- UNION ALL : 테이블이 결합된 순서대로 조회한 것을 확인.


-- UNION ALL : 중복된 데이터가 있더라도 이것을 제거하지 않고 결합한다. (비교Ⅹ)
--             결합된 테이블 순서대로 레코드를 결합한다. (정렬Ⅹ)

-- UNION     : 중복된 데이터가 있을 경우 제거한다. (비교)
--             첫 번째 컬럼을 기준으로 오름차순 정렬한다. (정렬)

-- UNION ALL 에는 정렬 기능읻 들어가지 않기 때문에 리소스 소모가 훨씬 적으므로
-- 실제로 더 많이 사용한다.


--※ UNION 은 항상 결과물의 첫 번째 컬럼을 기준으로
--  오름차순 정렬을 수행한다.
--  반면, UNION ALL 은 결합된 순서(쿼리문에서 테이블을 명시한 순서) 대로
--  조회한 결과를 있는 그대로 반환한다. (→ 정렬 없음)
--  이로 인해 UNION 이 부하가 더 크다. (→ 리소스 소모가 더 크다)
--  또한, UNION 은 결과물에 대한 중복된 레코드(행)가 존재할 경우
--   중복을 제거하고 1개 행만 조회된 결과를 반환하게 된다.




--○ 지금까지 주문받은 데이터를 통해
--   제품별 총 주문량을 조회할 수 있는 쿼리문을 구성한다.

-- TBL_JUMUN, TBL_JUMUNBACKUP 에서 
-- 총 꼬북칩, 빼빼로가 몇 번 주문되었는지 확인.


SELECT T.JECODE "제품명"
     , SUM(T.JUSU) "주문횟수"
FROM 
(    
    SELECT TJ.JECODE, TJ.JUSU
    FROM TBL_JUMUN TJ
    UNION ALL
    SELECT TB.JECODE, TB.JUSU
    FROM TBL_JUMUNBACKUP TB
) T
GROUP BY T.JECODE
ORDER BY 주문횟수 ASC;



SELECT T.JECODE "제품코드", SUM(T.JUSU) "주문수량"
FROM
(
    SELECT JECODE, JUSU
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT JECODE, JUSU
    FROM TBL_JUMUN
) T
GROUP BY T.JECODE;
--==>>
/*
제품코드	주문수량
꼬북칩	    40
오예스	    20
맛동산	    90
웨하스	    20
에이스	    40
포카칩	    80
오감자	    10
빅파이	    30
사또밥	    40
홈런볼	    50
빼빼로	    140
감자깡	    30
마이쮸	    20
오레오	    20
포스틱	    20
*/


--○ INTERSECT / MINUS (교집합 / 차집합)

-- TBL_JUMUNBACKUP 테이블과 TBL_JUMUN 테이블에서
-- 제품코드와 주문수량의 값이 똑같은 행만 추출해서 조회하고자 한다.




SELECT JECODE, JUSU
FROM TBL_JUMUNBACKUP
INTERSECT
SELECT JECODE, JUSU
FROM TBL_JUMUN;
--==>>
/*
[양쪽의 테이블에 모두 동일하게 들어있는 데이터들이다.]
맛동산	30
빼빼로	20
홈런볼	10
*/


SELECT JECODE, JUSU
FROM TBL_JUMUNBACKUP
MINUS
SELECT JECODE, JUSU
FROM TBL_JUMUN;
--> TBL_JUMUNBACKUP 에서 교집합이었던 데이터들을 제거하고 남은 데이터들만 조회된다.
--==>>
/*
감자깡	10
꼬북칩	30
마이쮸	20
맛동산	20
빅파이	10
빅파이	20
사또밥	10
사또밥	30
오예스	20
포스틱	20
포카칩	10
포카칩	20
포카칩	30
홈런볼	20
*/


--○ TBL_JUMUNBACKUP 테이블과 TBL_JUMUN 테이블을 대상으로
--   제품코드와 주문량의 값이 똑같은 행의 정보를
--   주문번호, 제품코드, 주문량, 주문일자 항목으로 조회한다.
--SELECT *
--FROM 
--(
--    SELECT JECODE, JUSU, JUNO, JUDAY
--    FROM TBL_JUMUNBACKUP
--    UNION ALL
--    SELECT JECODE, JUSU, JUNO, JUDAY
--    FROM TBL_JUMUN
--);
--
--SELECT *
--FROM TBL_JUMUN;



--○ TBL_JUMUNBACKUP 테이블과 TBL_JUMUN 테이블을 대상으로
--   제품코드와 주문량의 값이 똑같은 행의 정보를
--   주문번호, 제품코드, 주문량, 주문일자 항목으로 조회한다.

-- INNER JOIN 
SELECT U.JUNO, U.JECODE, U.JUSU, U.JUDAY
FROM 
(
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUN
) U
INNER JOIN
(    
    SELECT JECODE, JUSU
    FROM TBL_JUMUNBACKUP
    INTERSECT
    SELECT JECODE, JUSU
    FROM TBL_JUMUN
) I
ON U.JECODE = I.JECODE
   AND
   U.JUSU = I.JUSU
ORDER BY JUDAY;






-- 중첩 서브 쿼리
SELECT U.JUNO, U.JECODE, U.JUSU, U.JUDAY
FROM 
(
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUN
) U
WHERE (U.JECODE, U.JUSU) 
      IN
      (
        SELECT JECODE, JUSU
        FROM TBL_JUMUNBACKUP
        INTERSECT
        SELECT JECODE, JUSU
        FROM TBL_JUMUN
      );
   
   
   
SELECT JECODE, JUSU, JUNO, JUDAY
FROM TBL_JUMUNBACKUP
UNION ALL
SELECT JECODE, JUSU, JUNO, JUDAY
FROM TBL_JUMUN;
--==>>
/*
포스틱	20	1	2001-11-01 09:10:10
빅파이	10	2	2001-11-01 10:10:10
사또밥	30	3	2001-11-01 11:10:10
포카칩	20	4	2001-11-02 11:10:10
포카칩	30	5	2001-11-03 11:10:10
빅파이	20	6	2001-11-04 11:10:10
홈런볼	10	7	2001-11-05 11:10:10
홈런볼	10	8	2001-11-06 11:10:10
오예스	20	9	2001-11-07 11:10:10
사또밥	10	10	2001-11-08 11:10:10
빼빼로	20	11	2001-11-09 11:10:10
감자깡	10	12	2001-11-10 11:10:10
빼빼로	20	13	2001-11-11 11:10:10
홈런볼	20	14	2001-11-12 11:10:10
포카칩	10	15	2001-11-13 11:10:10
포카칩	20	16	2001-11-16 11:10:10
마이쮸	20	17	2001-11-17 11:10:10
맛동산	30	18	2001-11-18 11:10:10
맛동산	20	19	2001-11-19 11:10:10
꼬북칩	30	20	2001-11-20 11:10:10
꼬북칩	10	98764	2023-10-26 12:46:10
빼빼로	30	98765	2023-10-26 12:46:58
빼빼로	20	98766	2023-10-26 12:47:25
에이스	40	98767	2023-10-26 12:47:53
홈런볼	10	98768	2023-10-26 12:48:16
감자깡	20	98769	2023-10-26 12:48:38
맛동산	10	98770	2023-10-26 12:49:03
웨하스	20	98771	2023-10-26 12:49:25
맛동산	30	98772	2023-10-26 12:49:45
오레오	20	98773	2023-10-26 12:50:08
빼빼로	50	98774	2023-10-26 12:50:29
오감자	10	98775	2023-10-26 12:50:54
*/



SELECT JECODE, JUSU
FROM TBL_JUMUNBACKUP
INTERSECT
SELECT JECODE, JUSU
FROM TBL_JUMUN;
--==>>
/*
맛동산	30
빼빼로	20
홈런볼	10
*/


/*
    7	    홈런볼	10	2001-11-05 11:10:10
    8	    홈런볼	10	2001-11-06 11:10:10
   11	    빼빼로	20	2001-11-09 11:10:10
   13	    빼빼로	20	2001-11-11 11:10:10
   18	    맛동산	30	2001-11-18 11:10:10
98766	    빼빼로	20	2023-10-26 12:47:25
98768	    홈런볼	10	2023-10-26 12:48:16
98772	    맛동산	30	2023-10-26 12:49:45
*/




-- 4개의 레코드가 모두 동일한 것을 찾으므로 조회 번호가 없다.
-- 주문번호가 주문 데이터별로 모두 다 다르므로 불가능하다.
SELECT JUNO, JECODE, JUSU, JUDAY
FROM TBL_JUMUNBACKUP
INTERSECT
SELECT JUNO, JECODE, JUSU, JUDAY
FROM TBL_JUMUN;
--==>> 조회 결과 없음




-- 방법1.
SELECT T2.JUNO "주문번호", T1.JECODE "제품코드"
     , T1.JUSU "주문수량", T2.JUDAY "주문일자"
FROM
(
    SELECT JECODE, JUSU
    FROM TBL_JUMUNBACKUP
    INTERSECT
    SELECT JECODE, JUSU
    FROM TBL_JUMUN
)T1
JOIN
(
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUN
)T2 
ON T1.JECODE = T2.JECODE
   AND
   T1.JUSU = T2.JUSU;
--==>>
/*
7	    홈런볼	10	2001-11-05 11:10:10
8	    홈런볼	10	2001-11-06 11:10:10
11	    빼빼로	20	2001-11-09 11:10:10
13	    빼빼로	20	2001-11-11 11:10:10
18	    맛동산	30	2001-11-18 11:10:10
98766	빼빼로	20	2023-10-26 12:47:25
98768	홈런볼	10	2023-10-26 12:48:16
98772	맛동산	30	2023-10-26 12:49:45
*/





-- 방법 2.

-- 잘못된 WHERE 문!
SELECT T.*
FROM
(
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUN
) T
WHERE T.JECODE IN ('맛동산', '빼빼로', '홈런볼')
  AND T.JUSU IN (30, 20, 10)
-- 이렇게 사용하면 안된다!
-- 맛동산은 반드시 30개여야 하고
-- 빼빼로는 반드시 20개
-- 홈런볼은 반드시 10개 여야 하는데
-- 위와 같이 작성하면,
-- 맛동산 20개, 맛동산 10개도 모두 조건에 맞고
-- 빼빼로 30개, 10개도 모두 조건에 맞으며
-- 홈런볼 30개, 20개도 조건에 맞기 때문에 논리적으로 문제가 있다!

-- ★[즉, 제품코드와 주문 수량을 동시에 조건으로 넣어 주어야만 한다!!!!!]



SELECT T.*
FROM
(
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUN
) T
WHERE T.JECODE와 J.JUSU 의 묶음 결과가 '맛동산30', '뺴빼로20', '홈런볼10';



SELECT T.*
FROM
(
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUN
) T
WHERE (T.JECODE || T.JUSU) IN ('맛동산30', '빼빼로20', '홈런볼10');
     --> CONCAT(T.JECODE, T.JUSU)
     
/*
홈런볼	10	7	    2001-11-05 11:10:10
홈런볼	10	8	    2001-11-06 11:10:10
빼빼로	20	11	    2001-11-09 11:10:10
빼빼로	20	13	    2001-11-11 11:10:10
맛동산	30	18	    2001-11-18 11:10:10
빼빼로	20	98766	2023-10-26 12:47:25
홈런볼	10	98768	2023-10-26 12:48:16
맛동산	30	98772	2023-10-26 12:49:45
*/



SELECT T.*
FROM
(
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUN
) T
WHERE (T.JECODE || T.JUSU) IN ('맛동산30', '빼빼로20', '홈런볼10');


-- ⓐ 제품 코드와 주문 수량을 결합한 결과값을 반환하는 쿼리문
SELECT (JECODE || JUSU)
FROM TBL_JUMUNBACKUP
INTERSECT
SELECT (JECODE || JUSU)
FROM TBL_JUMUN;


SELECT T.*
FROM
(
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUN
) T
WHERE (T.JECODE || T.JUSU)
       IN
       (SELECT (JECODE || JUSU)  -- ⓐ 쿼리문을 서브쿼리로 사용하여
        FROM TBL_JUMUNBACKUP     --    제품코드와 주문 수량을 결합한 문자열을 반환하여
        INTERSECT               --     그 문자를 WHERE 조건식으로 사용한다.
        SELECT (JECODE || JUSU)
        FROM TBL_JUMUN);





-- 다시 선생님 설명 이어서!!
SELECT T.*
FROM
(
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUN
) T
WHERE (T.JECODE || T.JUSU) IN ('맛동산30', '빼빼로20', '홈런볼10');



-- 제품코드와 주문량을 문자열로 합친 결과를 반환하는 쿼리

SELECT CONCAT(JECODE, JUSU) 
FROM TBL_JUMUNBACKUP    
INTERSECT               
SELECT CONCAT(JECODE, JUSU) 
FROM TBL_JUMUN;



SELECT T.*
FROM
(
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT JECODE, JUSU, JUNO, JUDAY
    FROM TBL_JUMUN
) T
WHERE CONCAT(T.JECODE, T.JUSU)  IN (SELECT CONCAT(JECODE, JUSU) 
                                FROM TBL_JUMUNBACKUP    
                                INTERSECT               
                                SELECT CONCAT(JECODE, JUSU) 
                                FROM TBL_JUMUN);
--==>>
/*
홈런볼	10	7	    2001-11-05 11:10:10
홈런볼	10	8	    2001-11-06 11:10:10
빼빼로	20	11	    2001-11-09 11:10:10
빼빼로	20	13	    2001-11-11 11:10:10
맛동산	30	18	    2001-11-18 11:10:10
빼빼로	20	98766	2023-10-26 12:47:25
홈런볼	10	98768	2023-10-26 12:48:16
맛동산	30	98772	2023-10-26 12:49:45
*/




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

SELECT D.DEPTNO,D.DNAME, E.ENAME, E.SAL
FROM EMP E JOIN DEPT D
ON E.DEPTNO = D.DEPTNO;
--==>>
/*
10	ACCOUNTING	CLARK	2450
10	ACCOUNTING	KING    	5000
10	ACCOUNTING	MILLER	1300
20	RESEARCH	    JONES	2975
20	RESEARCH	    FORD	    3000
20	RESEARCH    	ADAMS	1100
20	RESEARCH    	SMITH	 800
20	RESEARCH	    SCOTT	3000
30	SALES	    WARD	    1250
30	SALES	    TURNER	1500
30	SALES	    ALLEN	1600
30	SALES	    JAMES	 950
30	SALES	    BLAKE	2850
30	SALES	    MARTIN	1250
*/


-- ON 조건이 없고, 중첩되는 컬럼을 어떤 테이블에서 가져올지
-- 테이블 명(또는 별칭 ALIAS)를 DEPTNO 에 명시해 주지 않아서 오류 발생.
SELECT DEPTNO, DNAME, ENAME, SAL
FROM EMP E JOIN DEPT D;
--==>> 에러 발생
--     (ORA-00905: missing keyword)


-- 나 이것 좀 자연스럽게 JOIN 해 줘...ㅎㅎ
-- 실행하면, 에러 안 나고 결과가 조회된다.... 우와...
SELECT DEPTNO, DNAME, ENAME, SAL
FROM EMP E NATURAL JOIN DEPT D;
--==>>
/*
10	ACCOUNTING	CLARK	2450
10	ACCOUNTING	KING	    5000
10	ACCOUNTING	MILLER	1300
20	RESEARCH	    JONES	2975
20	RESEARCH	    FORD    	3000
20	RESEARCH	    ADAMS	1100
20	RESEARCH	    SMITH	800
20	RESEARCH	    SCOTT	3000
30	SALES	    WARD	    1250
30	SALES	    TURNER	1500
30	SALES	    ALLEN	1600
30	SALES	    JAMES	950
30	SALES	    BLAKE	2850
30	SALES	    MARTIN	1250
*/
-- 제대로 결합되는지 확인하는 용도로 NATURAL JOIN 을 사용하는 것은 괜찮지만
-- 위의 JOIN은 모든 것을 오라클에게 맡겨버리는 것이므로 올바르지 않다.
-- NATURAL JOIN 을 하기 위해서는 오라클이 쿼리문의 컬럼과 테이블을 모두 분석해서
-- 처리해야 하기 때문에 굉장히 리소스 소모가 크다.

-- 이렇게 처리하지 말고, 우리가 직접 JOIN의 결합 규칙이나
-- 컬럼의 테이블명을 명시해 주도록 하는 것이 올바르다.



SELECT DEPTNO, DNAME, ENAME, SAL
FROM EMP E JOIN DEPT D
USING(DEPTNO);              --> JOIN할 때, DEPTNO 컬럼을 이용해서 JOIN 해 줘!
                            -- 중간에 한번 변환과정을 거치는 쿼리...

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



--○ TBL_EMP 테이블에서 급여가 가장 많은 사원의
--   사원번호, 사원명, 직종명, 급여 항목을 조회한다.

-- 급여가 가장 많은 사원의 사원번호, 사원명, 직종명, 급여 항목 조회

-- 중첩 서브 쿼리 (WHERE 절에 사용)
SELECT EMPNO "사원번호", ENAME "사원명", JOB "직종명", SAL "급여"
FROM TBL_EMP
WHERE SAL
      IN
      (SELECT MAX(SAL)
        FROM TBL_EMP);





-- INNER JOIN
SELECT E.*
FROM
(
    SELECT EMPNO "사원번호", ENAME "사원명", JOB "직종명", SAL "급여"
    FROM TBL_EMP
) E 
INNER JOIN
(
    SELECT MAX(SAL) "SAL"
    FROM TBL_EMP

) MS
ON E.급여 = MS.SAL;


-- 급여를 가장 많이 받는 사원의 급여

SELECT MAX(SAL)
FROM TBL_EMP;
--==>> 5000


SELECT EMPNO, ENAME, JOB, SAL
FROM TBL_EMP
WHERE (급여가 가장 많은 사원);



SELECT EMPNO, ENAME, JOB, SAL
FROM TBL_EMP
WHERE 급여 = (급여를 가장 많이 받는 사원의 급여);



SELECT EMPNO, ENAME, JOB, SAL
FROM TBL_EMP
WHERE SAL = (SELECT MAX(SAL)
             FROM TBL_EMP);
             
--==>> 7839	KING    	PRESIDENT	5000


-- 『=ANY』 

-- 『=ALL』


SELECT SAL
FROM TBL_EMP;
--==>
/*
800
1600
1250
2975
1250
2850
2450
3000
5000
1500
1100
950
3000
1300
1500
2000
1700
2500
1000
*/


SELECT EMPNO, ENAME, JOB, SAL
FROM TBL_EMP
WHERE SAL =ANY (800, 1600, 1250, 2975, 1250, 2850, 2450, 3000, 5000, 1500, 1100, 950, 3000, 1300
               ,1500, 2000, 1700);
               
-- 사원들의 급여 중, 괄호 안의 값과 하나라도 겹친다면 그 레코드를 조회한다.

SELECT EMPNO, ENAME, JOB, SAL
FROM TBL_EMP
WHERE SAL = ALL (800, 1600, 1250, 2975, 1250, 2850, 2450, 3000, 5000, 1500, 1100, 950, 3000, 1300
               ,1500, 2000, 1700);
-- 급여가 800 이기도 하면서 1600 이기도 하면서...
-- 괄호 안에 있는 것들과 모두 같은 값들을 찾겠다는 의미 -> 논리적으로 잘못 되었다.




SELECT EMPNO, ENAME, JOB, SAL
FROM TBL_EMP
WHERE SAL >= ALL (800, 1600, 1250, 2975, 1250, 2850, 2450, 3000, 5000, 1500, 1100, 950, 3000, 1300
               ,1500, 2000, 1700);
-- 모든 것들과 비교했을 때 크거나 같은 급여다!! 그것이 바로 5000! 최댓값!!!
-- 하나하나 각각의 사원들과 모두 비교해 봤을 때 다 크거나 같으려면
-- KING 의 SAL 값인 5000밖에 가능한 값이 없다!

-- 괄호 안의 값은 어떤 쿼리?
-- 모든 사원의 SAL 을 조회하는 쿼리!
SELECT SAL
FROM TBL_EMP;
-- 따라서 위의 쿼리를 ALL 옆의 괄호에 서브 쿼리로 사용해 주게 되면 같은 결과를 반환한다.



-- WHERE에 집계 함수를 쓰지 않고 MAX값을 파악하여 연산할 수 있다.
SELECT EMPNO, ENAME, JOB, SAL
FROM TBL_EMP
WHERE SAL >= ALL (SELECT SAL
                  FROM TBL_EMP);




--○ TBL_EMP 테이블에서 20번 부서에 근무하는 사원들 중 급여가 가장 많은 사람의
--   사원번호, 사원명, 직종명, 급여 항목을 조회하는 쿼리문을 구성한다.



-- ALL 을 이용하여 WHERE 절에 집계함수를 쓰지 않고 풀이한 방식
-- 쌤이 알려주신 신기한 방식
SELECT EMPNO "사원번호", ENAME "사원명", JOB "직종명", SAL "급여"
FROM TBL_EMP
WHERE DEPTNO = 20
      AND
      SAL >= ALL(SELECT SAL
                 FROM TBL_EMP
                 WHERE DEPTNO = 20);



-- 이건... 내가 원래 풀던 방식.
-- 중첩 서브 쿼리를 이용해서 MAX(SAL) 값을 이용하는 방식
SELECT EMPNO "사원번호", ENAME "사원명", JOB "직종명", SAL "급여"
FROM TBL_EMP
WHERE DEPTNO = 20
      AND
      SAL
      IN
      (SELECT MAX(SAL)
       FROM TBL_EMP
       WHERE DEPTNO = 20);
       



SELECT 사원번호, 사원명, 직종명, 급여
FROM TBL_EMP
WHERE SAL = (가장많은급여)
      DEPTNO = 20;



SELECT EMPNO, ENAME, JOB, SAL
FROM TBL_EMP
WHERE SAL = (가장많은급여)
      AND
      DEPTNO = 20;



SELECT EMPNO, ENAME, JOB, SAL
FROM TBL_EMP
WHERE SAL = (SELECT MAX(SAL)
             FROM TBL_EMP) -- 급여가 가장 많은 사원 KING = 5000이 들어간다.
                           -- SUB QUARY 내에서도 조건을 명시해 주어야 한다.
      AND   
      DEPTNO = 20;         
--==>> 조회 결과 없음




-- 외부 쿼리 밑에 비록 DEPTNO = 20이 있지만
-- 서브 쿼리 내부에도 DEPTNO = 20이라는 조건을 넣어야 한다!!

SELECT EMPNO, ENAME, JOB, SAL
FROM TBL_EMP
WHERE SAL = (SELECT MAX(SAL)
             FROM TBL_EMP
             WHERE DEPTNO = 20) -- 급여가 가장 많은 사원 KING = 5000이 들어간다.
                                -- SUB QUARY 내에서도 조건을 명시해 주어야 한다.
      AND   
      DEPTNO = 20; 
-- 안의 서브쿼리에서 얻어내는 MAX(SAL) 의 값을 구해내는 과정에서 조건을 구해야 하므로
-- 내부에도 WHERE DEPTNO = 20 을 작성해 준 것!!
--> 따라서, 서브 쿼리 내부에서 WHERE 조건문은 절대 생략되어선 안되는 절이다.

--==>>
/*
7788	SCOTT	ANALYST	3000
7902	    FORD	    ANALYST	3000
*/





SELECT EMPNO, ENAME, JOB, SAL
FROM TBL_EMP
WHERE SAL >=  ALL(SELECT SAL
                 FROM TBL_EMP
                 WHERE DEPTNO = 20)  -- 이때에도 이 조건문은 생략되어선 안 된다.
                
                -- 내부 쿼리 결과값
                    /*
                    800
                    2975
                    3000
                    1100
                    3000
                    */
      AND   
      DEPTNO = 20;