냥코딩쟝
Published 2023. 3. 24. 15:23
day09~day10 -java spring notes-/db

-- SCOTT --
1. emp , salgrade 테이블을 사용해서 아래와 같이 출력. [JOIN] 사용

SELECT e.ename, e.sal, s.losal || '~' || s.hisal, s.grade
FROM emp e, salgrade s
WHERE e.sal BETWEEN s.losal AND s.hisal;

SELECT ename, sal, losal || '~' || hisal, grade
FROM emp
JOIN salgrade ON sal BETWEEN losal AND hisal;

    ename   sal    grade
    ---------------------
    SMITH   800       1
    ALLEN   1900   3
    WARD   1750   3
    JONES   2975   4
    MARTIN   2650   4
    BLAKE   2850   4
    CLARK   2450   4
    KING   5000   5
    TURNER   1500   3
    JAMES   950   1
    FORD   3000   4
    MILLER   1300   2
    
문제) deptno, dname, ename, hiredate, sal, grade 컬럼 조회(join)
SELECT d.deptno, dname, ename, hiredate, sal, grade
FROM dept d, emp e, salgrade s
WHERE d.deptno = e.deptno AND e.sal BETWEEN s.losal AND s.hisal;
    
SELECT d.deptno, dname, ename, hiredate, sal, grade
FROM dept d JOIN emp e ON d.deptno = e.deptno
            JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal;
    
1-2. 위의 결과에서 등급(grade)가 1등급인 사원만 조회하는 쿼리 작성  
  ( 조건 :  TOP-N 방식 사용 )
  
  SELECT empno, ename, sal, grade
  FROM emp JOIN salgrade ON sal BETWEEN losal AND hisal
  WHERE grade = 1;

결과)
     EMPNO ENAME             SAL      GRADE
---------- ---------- ---------- ----------
      7369 SMITH             800          1
      7900 JAMES             950          1      
      
2. emp 에서 최고급여를 받는 사원의 정보 출력 ( JOIN ~ ON 구문 )
  ( 조건 : 아래 컬럼 출력 )

SELECT dname, ename, sal + NVL(comm, 0) pay
FROM dept d, emp e
WHERE d.deptno(+) = e.deptno -- JOIN 조건
    AND sal + NVL(comm, 0) = (
                                SELECT MAX(sal + NVL(comm, 0)) max_pay
                                FROM emp
                             );
-- 근데 이렇게 하면 INNER JOIN이라 양쪽에서 공통적으로 갖는 deptno의 데이터만 가져와 제대로된 결과가 나오지 않는다.
-- RIGHT OUTER JOIN으로 바꾸어주면 원하는 결과를 얻을 수 있다.

SELECT dname, ename, sal + NVL(comm, 0) pay
FROM dept d RIGHT OUTER JOIN emp e ON d.deptno = e.deptno
WHERE sal + NVL(comm, 0) = (
                                SELECT MAX(sal + NVL(comm, 0)) max_pay
                                FROM emp
                             );

DNAME          ENAME             PAY
-------------- ---------- ----------
ACCOUNTING     KING             5000

문제) RANK()
-- 순위를 매기려면 정렬이 되어야 한다.
WITH
    temp AS (
        SELECT dname, ename, sal + NVL(comm, 0) pay
            , RANK() OVER(ORDER BY sal + NVL(comm, 0) DESC) "R"
            , DENSE_RANK() OVER(ORDER BY sal + NVL(comm, 0) DESC) "DR"
            , ROW_NUMBER() OVER(ORDER BY sal + NVL(comm, 0) DESC) "RN"
        FROM dept d RIGHT OUTER JOIN emp e ON d.deptno = e.deptno
    )
    SELECT t.*
    FROM temp t
    WHERE t.R = 1;
    WHERE t.R = -3;
    WHERE t.R BETWEEN 3 AND 5;


문제) DENSE_RANK()

문제) ROW_NUMBER()

문제) TOP-N 방식
1) FROM 인라인 뷰 에서 급여순으로 정렬
2) 서브쿼리 묶기
3) 의사컬럼으로 순번
SELECT t.*, ROWNUM 순번
FROM (
    SELECT dname, ename, sal + NVL(comm, 0) pay
    FROM dept d RIGHT OUTER JOIN emp e ON d.deptno = e.deptno
    ORDER BY pay DESC
    ) t
WHERE ROWNUM <= 3;



2-2. emp 에서 각 부서별 최고급여를 받는 사원의 정보 출력 ( JOIN )

    DEPTNO DNAME          ENAME             PAY
---------- -------------- ---------- ----------
        10 ACCOUNTING     KING             5000
        20 RESEARCH       FORD             3000
        30 SALES          BLAKE            2850

1) 상관서브 쿼리로 풀기(서브쿼리가 main이랑 관련있기 때문에 다 한번에 실행해야 함.)
SELECT d.deptno, dname, ename, sal + NVL(comm,0) pay
FROM dept d FULL JOIN emp e ON d.deptno = e.deptno
WHERE sal + NVL(comm, 0) = (
            SELECT MAX(sal + NVL(comm, 0))
            FROM emp
            WHERE deptno = d.deptno
            );

 

 


2) 문제점이 있는 풀이
SELECT d.deptno, dname, ename, sal + NVL(comm,0) pay
FROM dept d FULL JOIN emp e ON d.deptno = e.deptno
WHERE sal + NVL(comm, 0) IN (
            SELECT MAX(sal + NVL(comm, 0))
            FROM emp
            GROUP BY deptno
            );

3) 순위 함수
SELECT t.*
FROM (
        SELECT d.deptno, dname, ename, sal + NVL(comm,0) pay
            , ROW_NUMBER() OVER(PARTITION BY d.deptno ORDER BY sal + NVL(comm, 0) DESC) 순위
            -- PARTITION으로 부서별로 정렬 후 내림차순 정렬해서 보여줌
        FROM dept d RIGHT JOIN emp e ON d.deptno = e.deptno --RIGHT JOIN 주면 사원이 없는 부서는 안 나옴
    ) t
WHERE 순위 <= 1;


3. emp 에서 각 사원의 급여가 전체급여의 몇 %가 되는 지 조회.
       ( %   소수점 3자리에서 반올림하세요 )
            무조건 소수점 2자리까지는 출력.. 7.00%,  3.50%     

SELECT SUM(sal + NVL(comm, 0)) totalpay
FROM emp;

SELECT ename, sal + NVL(comm, 0) pay
FROM emp;

SELECT t.*
    , ROUND(t.pay/t.totalpay * 100, 2) || '%' "비율"
    , TO_CHAR(ROUND(t.pay/t.totalpay * 100, 2), '99.00') || '%' "비율"
FROM (
    SELECT ename, sal + NVL(comm, 0) pay
        , (SELECT SUM(sal + NVL(comm, 0)) FROM emp) totalpay
    FROM emp
    )t;


ENAME             PAY   TOTALPAY 비율     
---------- ---------- ---------- -------
SMITH             800      27125   2.95%
ALLEN            1900      27125   7.00%
WARD             1750      27125   6.45%
JONES            2975      27125  10.97%
MARTIN           2650      27125   9.77%
BLAKE            2850      27125  10.51%
CLARK            2450      27125   9.03%
KING             5000      27125  18.43%
TURNER           1500      27125   5.53%
JAMES             950      27125   3.50%
FORD             3000      27125  11.06%
MILLER           1300      27125   4.79%

12개 행이 선택되었습니다.         
        
4. emp 에서 가장 빨리 입사한 사원 과 가장 늦게(최근) 입사한 사원의 차이 일수 ?         

SELECT ABS(MAX(hiredate) - MIN(hiredate))
FROM emp;

5. insa 에서 사원들의 만나이 계산해서 출력
  ( 만나이 = 올해년도 - 출생년도          - 1( 생일이지나지 않으면) )

SELECT*
FROM insa;

ㄱ. 올해연도
ㄴ. 생일연도 4자리
ㄷ. 생일 전/후 체크

SELECT t.name, t.ssn 
    , ㄱ-ㄴ+1 CountingAge
    , ㄱ-ㄴ+ DECODE(ㄷ, -1, -1, 0) AmericanAge
FROM (
        SELECT name, ssn
            , TO_CHAR(SYSDATE, 'YYYY') ㄱ -- 2023
            -- 1800/1900/2000 년대는 어떻게?
            , SUBSTR(ssn, 0, 2) + CASE
                WHEN SUBSTR(ssn, -7, 1) IN (1,2,5,6) THEN 1900
                WHEN SUBSTR(ssn, -7, 1) IN (3,4,7,8) THEN 2000
                WHEN SUBSTR(ssn, -7, 1) IN (9,0) THEN 1800
             END ㄴ
            -- 생일 지나면 1, 지나지 않으면 -1, 오늘이 생일이면 0
            , SIGN(TO_CHAR(SYSDATE, 'MMDD') - SUBSTR(ssn, 3, 4)) ㄷ    
        FROM insa
    ) t; 
  
  
  
6. insa 테이블에서 아래와 같이 결과가 나오게 ..
     [총사원수]      [남자사원수]      [여자사원수] [남사원들의 총급여합]  [여사원들의 총급여합] [남자-max(급여)] [여자-max(급여)]
---------- ---------- ---------- ---------- ---------- ---------- ----------
        60                31              29           51961200                41430400                  2650000          2550000
        
SELECT COUNT(*) 총사원수
    , COUNT( DECODE( MOD(SUBSTR(ssn, -7, 1), 2),1,'O')) 남자사원수
    , COUNT( DECODE( MOD(SUBSTR(ssn, -7, 1), 2),1,'O')) 여자사원수
    , TO_CHAR(SUM(DECODE( MOD(SUBSTR(ssn, -7, 1), 2), 1, basicpay + sudang)), 'L9,999,999,999') 남자총급여합
    , SUM(DECODE( MOD(SUBSTR(ssn, -7, 1), 2), 0, basicpay + sudang)) 여자총급여합
    , TO_CHAR(MAX(DECODE( MOD(SUBSTR(ssn, -7, 1), 2), 1, basicpay + sudang)), 'L9,999,999,999') 남자MAX급여합
    , MAX(DECODE( MOD(SUBSTR(ssn, -7, 1), 2), 0, basicpay + sudang)) 여자MAX급여합
FROM insa;
      
7. TOP-N 방식으로 풀기 ( ROWNUM 의사 컬럼 사용 )
   emp 에서 최고급여를 받는 사원의 정보 출력  
  
    DEPTNO ENAME             PAY   PAY_RANK
---------- ---------- ---------- ----------
        10 KING             5000          1
        
SELECT t.*, ROWNUM
FROM (
        SELECT deptno, ename, sal + NVL(comm, 0) pay
        FROM emp
        ORDER BY pay DESC
    ) t
WHERE ROWNUM = 1;


8.순위(RANK) 함수 사용해서 풀기 
   emp 에서 각 부서별 최고급여를 받는 사원의 정보 출력
   
    DEPTNO ENAME             PAY DEPTNO_RANK
---------- ---------- ---------- -----------
        10 KING             5000           1
        20 FORD             3000           1
        30 BLAKE            2850           1
        
-- 서브쿼리 사용
SELECT t.* 
FROM (
    SELECT deptno, ename, sal + NVL(comm, 0) pay
        , RANK() OVER(ORDER BY sal + NVL(comm, 0) DESC) "전체 순위"
        , RANK() OVER(PARTITION BY deptno ORDER BY sal + NVL(comm, 0) DESC) "부서순위"
    FROM emp
    )t
WHERE "부서순위" = 1;

-- JOIN 사용
ㄱ. 각부서의 최고 급여액
SELECT deptno, MAX(sal + NVL(comm, 0))
FROM emp
GROUP BY deptno;
--
SELECT a.deptno, b.ename, a.max_pay, 1 AS deptno_rank -- 고정값 1 주면 1등 찍힘
FROM (
    SELECT deptno, MAX(sal + NVL(comm, 0)) max_pay
    FROM emp
    GROUP BY deptno
    ) a JOIN emp b ON a.deptno = b.deptno
WHERE a.max_pay = b.sal+NVL(comm, 0); -- 최고값하고 같은 부서이면서 같은 사람
   
9. emp테이블에서 각 부서의 사원수, 부서총급여합, 부서평균을 아래와 같이 출력하는 쿼리 작성.
결과)
    DEPTNO       부서원수       총급여합            평균
---------- ----------       ----------    ----------
        10          3          8750       2916.67
        20          3          6775       2258.33
        30          6         11600       1933.33      
        
        
-- 첫번째 방법 --
SELECT deptno
    , COUNT(*) 부서원수
    , SUM(sal + NVL(comm, 0)) 총급여합
    , TO_CHAR(ROUND(AVG(sal + NVL(comm, 0)), 2), '9999.00') 평균
FROM emp
GROUP BY deptno
ORDER BY deptno;

10-1.  emp 테이블에서 30번인 부서의 최고, 최저 SAL을 출력하는 쿼리 작성.
결과)
  MIN(SAL)   MAX(SAL)
---------- ----------
       950       2850
       
SELECT MAX(sal), MIN(sal)
FROM emp
WHERE deptno = 30;

각 부서별 최대, 최솟값
SELECT deptno, MAX(sal), MIN(sal)
FROM emp
GROUP BY deptno
ORDER BY deptno;
       

10-2.  emp 테이블에서 30번인 부서의 최고, 최저 SAL를 받는 사원의 정보 출력하는 쿼리 작성.

결과)
     EMPNO ENAME      HIREDATE        SAL
---------- ---------- -------- ----------
      7698 BLAKE      81/05/01       2850
      7900 JAMES      81/12/03        950      
-- 서브쿼리 이용
SELECT empno, ename, hiredate, sal
FROM emp
WHERE deptno =30
AND sal IN (
    (SELECT MAX(sal) FROM emp WHERE deptno = 30),
    (SELECT MIN(sal) FROM emp WHERE deptno = 30)
   );
   
-- JOIN 이용
SELECT empno, ename, hiredate, sal
FROM (
    SELECT MAX(sal) max, MIN(sal) min
    FROM emp
    WHERE deptno = 30
    ) a, emp b
WHERE b.deptno =30 AND b.sal = a.max OR b.sal = a.min;

11.  insa 테이블에서 
[실행결과]
부서명     총사원수 부서사원수 성별  성별사원수  부/전%   부성/전%   성/부%
개발부       60       14         F       8       23.3%     13.3%       57.1%
개발부       60       14         M       6       23.3%     10%       42.9%
기획부       60       7         F       3       11.7%   5%   4       2.9%
기획부       60       7         M       4       11.7%   6.7%       57.1%
영업부       60       16         F       8       26.7%   13.3%       50%
영업부       60       16         M       8       26.7%   13.3%       50%
인사부       60       4         M       4       6.7%   6.7%       100%
자재부       60       6         F       4       10%       6.7%       66.7%
자재부       60       6         M       2       10%       3.3%       33.3%
총무부       60       7         F       3       11.7%   5%           42.9%
총무부       60       7         M    4       11.7%   6.7%       57.1%
홍보부       60       6         F       3       10%       5%           50%
홍보부       60       6         M       3       10%       5%           50%             

1) 총 사원 수 가져오기
SELECT COUNT(*)
FROM insa;
2) 부서 사원수
SELECT buseo, COUNT(*) 부서사원수
FROM insa
GROUP BY buseo;
3) 부서별 성별, 사원 수
SELECT buseo, MOD(SUBSTR(ssn, -7, 1), 2) 성별, COUNT(*) 부서별사원수
FROM insa
GROUP BY buseo, MOD(SUBSTR(ssn, -7, 1), 2)
ORDER BY buseo, MOD(SUBSTR(ssn, -7, 1), 2);
--
SELECT t2.*
    , ROUND(t2.부서사원수/t2.총사원수 * 100, 2) || '%' "부/전%"
    , ROUND(t2.성별사원수/t2.총사원수 * 100, 2) || '%' "부성/전%"
    , ROUND(t2.성별사원수/t2.부서사원수 * 100, 2) || '%' "부성/부서%"
FROM (
    SELECT t.buseo "부서명"
        ,(SELECT COUNT(*) FROM insa) "총사원수"
        ,(SELECT COUNT(*) FROM insa WHERE buseo = t.buseo) "부서사원수"
        , t.gender "성별", COUNT(*) "성별사원수"
    FROM (
            SELECT buseo, name, ssn
                , DECODE(MOD(SUBSTR(ssn, -7, 1), 2), 1, 'M', 'F') gender
            FROM insa
        )t
    GROUP BY t.buseo, t.gender
    ORDER BY t.buseo, t.gender
) t2;

12. insa테이블에서 여자인원수가 5명 이상인 부서만 출력.
-- 첫번째 방법: 서브쿼리 이용 --
SELECT t.*
FROM (
        SELECT buseo, COUNT(*) 여자사원수
        FROM insa
        WHERE MOD(SUBSTR(ssn, -7, 1), 2) = 0
        GROUP BY buseo
    ) t
WHERE t.여자사원수 >= 5;

-- 두번째 방법: GROUP BY절의 조건절인 HAVING절 이용 --
SELECT buseo, COUNT(*) 여자사원수
FROM insa
WHERE MOD(SUBSTR(ssn, -7, 1), 2) = 0
GROUP BY buseo
HAVING COUNT(*) >= 5; -- 이거와 같다. WHERE t.여자사원수 >= 5;

13. insa 테이블에서 급여(pay= basicpay+sudang)가 상위 15%에 해당되는 사원들 정보 출력 
SELECT t.*
FROM (
    SELECT buseo, name, basicpay+sudang pay
        , RANK() OVER(ORDER BY basicpay+sudang DESC) "급여순위"
    FROM insa
    ) t
WHERE 급여순위 <= (SELECT COUNT(*) FROM insa) * 0.15;


14. emp 테이블에서 sal의 전체사원에서의 등수 , 부서내에서의 등수를 출력하는 쿼리 작성
SELECT deptno, ename, sal
    , RANK() OVER(ORDER BY sal DESC) "전체등수"
    , RANK() OVER(PARTITION BY deptno ORDER BY sal DESC) "부서등수"
    , (SELECT COUNT(*) + 1 FROM emp b WHERE b.sal > a.sal) "전체등수2"
    , (SELECT COUNT(*) + 1 FROM emp b WHERE b.sal > a.sal AND b.deptno = a.deptno) "부서등수2"
FROM emp a
ORDER BY deptno ASC;

문제) 20번, 40번 부서 제외하고 조회
부서 사원수가 3명 이상인 부서정보만 출력


SELECT e.deptno, d.dname, COUNT(*)
FROM emp e
JOIN dept d ON e.deptno = d.deptno
WHERE e.deptno NOT IN(20, 40)
GROUP BY e.deptno, d.dname
HAVING COUNT(*) >= 3;

------------
SELECT buseo, jikwi, COUNT(*)
FROM insa i
GROUP BY buseo, jikwi
ORDER BY buseo, jikwi
JOIN dept d ON e.deptno = d.deptno
WHERE e.deptno NOT IN(20, 40)
GROUP BY e.deptno, d.dname
HAVING COUNT(*) >= 3;

 

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


1. emp 테이블에서 job 별로 사원수 몇 명 조회(출력) 하는 쿼리 작성.

  [실행결과]
       CLERK   SALESMAN  PRESIDENT    MANAGER    ANALYST
---------- ---------- ---------- ---------- ----------
         3          4          1          3          1

2. emp 테이블에서  [JOB별로] 각 월별 입사한 사원의 수를 조회 
  ㄱ. COUNT(), DECODE() 사용

JOB         COUNT(*)         1월         2월         3월         4월         5월         6월         7월         8월         9월        10월        11월        12월
--------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
CLERK              3          1          0          0          0          0          0          0          0          0          0          0          2
SALESMAN           4          0          2          0          0          0          0          0          0          2          0          0          0
PRESIDENT          1          0          0          0          0          0          0          0          0          0          0          1          0
MANAGER            3          0          0          0          1          1          1          0          0          0          0          0          0
ANALYST            1          0          0          0          0          0          0          0          0          0          0          0          1

  ㄴ. GROUP BY 절 사용

         월        인원수
---------- ----------
         1          1
         2          2
         4          1
         5          1
         6          1
         9          2
        11          1
        12          3

8개 행이 선택되었습니다. 

3. emp 테이블에서 각 부서별 급여 많이 받는 사원 2명씩 출력
  실행결과)
       SEQ      EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- ---------- --------- ---------- -------- ---------- ---------- ----------
         1       7839 KING       PRESIDENT            81/11/17       5000                    10
         2       7782 CLARK      MANAGER         7839 81/06/09       2450                    10
         1       7902 FORD       ANALYST         7566 81/12/03       3000                    20
         2       7566 JONES      MANAGER         7839 81/04/02       2975                    20
         1       7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
         2       7654 MARTIN     SALESMAN        7698 81/09/28       1250       1400         30
         

-- HR --
    
SELECT TO_CHAR( TO_DATE('2022.01.03'), 'IW' ) -- ISO 표준 주   월~일까지 1주.
, TO_CHAR( TO_DATE('2022.01.09'), 'IW' )
 , TO_CHAR( TO_DATE('2022.02.04'), 'WW' )  -- 년의 주          1~7  끝어짐
 , TO_CHAR( TO_DATE('2022.02.05'), 'WW' )
FROM dual;

 

-- SCOTT --

--------------------------------------------------------------------------------
-- 복습문제 
--------------------------------------------------------------------------------

  [실행결과]
       CLERK   SALESMAN  PRESIDENT    MANAGER    ANALYST
---------- ---------- ---------- ---------- ----------
         3          4          1          3          1

--1) GROUP BY job       + COUNT(*) 사용
        SELECT job, COUNT(*) "사원수"
        FROM emp
        GROUP BY job;

--2) 가로 출력
        SELECT
            COUNT (DECODE( job, 'CLERK', 1) ) CLERK
            ,COUNT (DECODE( job, 'SALESMAN', 1) ) SALESMAN
            ,COUNT (DECODE( job, 'PRESIDENT', 1) ) PRESIDENT
            ,COUNT (DECODE( job, 'MANAGER', 1) ) MANAGER
            ,COUNT (DECODE( job, 'ANALYST', 1) ) ANALYST
        FROM emp;


--[피봇 (PIVOT) / 언피봇(UNPIVOT) 함수]
    1. 오라클 11g부터 제공하는 함수
    2. 행과 열을 뒤집는 함수
    3. [형식]
        SELECT * 
        FROM (피벗 대상 쿼리문) -- 1. 서버쿼리(세로를 가로로 만들기)
        PIVOT (그룹함수(집계컬럼) FOR 피벗컬럼(대상) IN(피벗컬럼 값 AS 별칭...))
    4.  순서는
        1)피벗 대상 쿼리문
        2) IN(목록)
        3) FOR 피벗컬럼
        4) 그룹함수(집게컬럼)

        1) SELECT job FROM emp;
        2) IN(목록)
        3) FOR 피벗컬럼
        4) 그룹함수(집게컬럼)

    예)
        SELECT *
        FROM (
                SELECT job 
                FROM emp
              ) 
        PIVOT (COUNT(job) FOR job IN('CLERK', 'SALESMAN', 'PRESIDENT', 'MANAGER', 'ANALYST' ))









2. emp 테이블에서  [JOB별로] 각 월별 입사한 사원의 수를 조회 



  ㄱ. COUNT(), DECODE() 사용
  
  

  
  

JOB         COUNT(*)         1월         2월         3월         4월         5월         6월         7월         8월         9월        10월        11월        12월
--------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
CLERK              3          1          0          0          0          0          0          0          0          0          0          0          2
SALESMAN           4          0          2          0          0          0          0          0          0          2          0          0          0
PRESIDENT          1          0          0          0          0          0          0          0          0          0          0          1          0
MANAGER            3          0          0          0          1          1          1          0          0          0          0          0          0
ANALYST            1          0          0          0          0          0          0          0          0          0          0          0          1

SELECT job, COUNT(*)
    , COUNT(decode( to_char(hiredate, 'MM'), '01', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '02', 'O')) "02월"
    , count(decode( to_char(hiredate, 'mm'), '03', 'O')) "03월"
    , count(decode( to_char(hiredate, 'mm'), '04', 'O')) "04월"
    , count(decode( to_char(hiredate, 'mm'), '05', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '06', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '07', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '08', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '09', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '10', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '11', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '12', 'O')) "12월"
FROM emp
GROUP BY JOB;


SELECT job, EXTRACT( MONTH FROM hiredate) 월 , COUNT(*) 인원수
FROM emp
GROUP BY job, EXTRACT( MONTH FROM hiredate)
ORDER BY job, 월



  ㄴ. GROUP BY 절 사용

         월        인원수
---------- ----------
         1          1
         2          2
         4          1
         5          1
         6          1
         9          2
        11          1
        12          3

8개 행이 선택되었습니다. 

--1)
SELECT TO_NUMBER(TO_CHAR( hiredate, 'MM' ) )월, COUNT(*) 인원수
FROM emp
GROUP BY TO_NUMBER(TO_CHAR(hiredate, 'MM' ) )
ORDER BY TO_NUMBER(TO_CHAR(hiredate, 'MM' ) );

--2) EXTRACT
SELECT EXTRACT( MONTH FROM hiredate)월, COUNT(*) 인원수
FROM emp
GROUP BY EXTRACT( MONTH FROM hiredate)
ORDER BY 월;


 [문제]   피봇함수를 사용해서 아래와 같이 출력.
 JOB               1월          2          3          4          5          6          7          8          9         10         11         12
--------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
CLERK              1          0          0          0          0          0          0          0          0          0          0          2
SALESMAN           0          2          0          0          0          0          0          0          2          0          0          0
PRESIDENT          0          0          0          0          0          0          0          0          0          0          1          0
MANAGER            0          0          0          1          1          1          0          0          0          0          0          0
ANALYST            0          0          0          0          0          0          0          0          0          0  
    1) 피봇 대상 쿼리
      SELECT EXTRACT( MONTH FROM hiredate )  hire_month 
      FROM emp;
    2) IN ( 목록 )
       1,2,3,4,5,6,7,8,9, 10, 11, 12
    3) FOR 피봇 컬럼
          hire_month
    4) 집계함수(컬럼 ))
       COUNT( hire_month )
        -- 전체 사원들이 입사한 월별 사원수 파악
        SELECT *
        FROM (
                SELECT EXTRACT( MONTH FROM hiredate )  hire_month 
                FROM emp
              ) 
        PIVOT (COUNT(hire_month ) FOR hire_month  IN(1,2,3,4,5,6,7,8,9, 10, 11, 12 ));
        
        -- 전체 사원들이 입사한 월별 사원수 파악
        SELECT *
        FROM (
                SELECT  job,  EXTRACT( MONTH FROM hiredate )  hire_month 
                FROM emp
              ) 
        PIVOT (COUNT(hire_month ) FOR hire_month  IN(1 AS "1월",2,3,4,5,6,7,8,9, 10, 11, 12 ));
    
    -- [ UNPIVOT() 정리 ]

3. emp 테이블에서 각 부서별 급여 많이 받는 사원 2명씩 출력
  실행결과)
       SEQ      EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- ---------- --------- ---------- -------- ---------- ---------- ----------
         1       7839 KING       PRESIDENT            81/11/17       5000                    10
         2       7782 CLARK      MANAGER         7839 81/06/09       2450                    10
         1       7902 FORD       ANALYST         7566 81/12/03       3000                    20
         2       7566 JONES      MANAGER         7839 81/04/02       2975                    20
         1       7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
         2       7654 MARTIN     SALESMAN        7698 81/09/28       1250       1400         30
   -- 1) TOP-N 방식
   -- 2) RANK 함수 
   SELECT t.*
   FROM (
       SELECT empno, ename, job, mgr, hiredate, sal , comm, deptno
           , RANK() OVER(  PARTITION BY deptno ORDER BY  sal + NVL(comm, 0)  ) SEQ
       FROM emp
   ) t
   WHERE seq <= 2;    
--------------------------------------------------------------------------------   
[피봇문제 1] emp 테이블에서 
                  1등급  2등급 ... 5등급
                  2     3          1
   -- 등급) salgrade 테이블  - grade, losal, hisal  + emp 테이블 조인
   --            부모,자식테이블 관계 X
   --            NON EQUI JOIN      조건   BETWEEN ~ AND 연산자
   SELECT empno, ename, sal , grade
   FROM emp e JOIN salgrade s  ON e.sal BETWEEN s.losal AND s.hisal;
    -- 각 sal등급의 인원수 몇 명인지 조회 ? 
    1) GROUP BY
    
    SELECT grade || '등급' , COUNT(*) 사원수
    FROM (
         SELECT empno, ename, sal , grade
         FROM emp e JOIN salgrade s  ON e.sal BETWEEN s.losal AND s.hisal
    ) t
    GROUP BY grade
    ORDER BY grade ASC;
    
    2) COUNT() + DECODE()
    
    SELECT 
          COUNT(  DECODE( grade, 1 , 'O'  ) ) "1등급"
        , COUNT(  DECODE( grade, 2 , 'O'  ) ) "2등급"
        , COUNT(  DECODE( grade, 3 , 'O'  ) ) "3등급"
        , COUNT(  DECODE( grade, 4 , 'O'  ) ) "4등급"
        , COUNT(  DECODE( grade, 5 , 'O'  ) ) "5등급"
    FROM (
         SELECT empno, ename, sal , grade
         FROM emp e JOIN salgrade s  ON e.sal BETWEEN s.losal AND s.hisal
    ) t;
    
    3) PIVOT()
       (1) 피봇대상
       SELECT *
       FROM ( 
            SELECT grade
            FROM emp e JOIN salgrade s  ON e.sal BETWEEN s.losal AND s.hisal
       )
       PIVOT( COUNT(grade) FOR grade IN ( 1 AS "1등급", 2, 3, 4, 5 ) );
    
   11:00 수업 시작~ 
[피봇문제 2] emp 테이블에서 년도별 입사사원수를 조회
         ( 1980, 1981, 1982 )
    SELECT DISTINCT TO_CHAR( hiredate, 'YYYY') YEAR
    FROM emp;

   1) GROUP BY
    SELECT TO_CHAR( hiredate, 'YYYY') HIRE_YEAR, COUNT(*) 사원수
    FROM emp
    GROUP BY TO_CHAR( hiredate, 'YYYY')
    ORDER BY HIRE_YEAR;
   
   2) COUNT(), DECODE()
   SELECT 
      COUNT(  DECODE( TO_CHAR( hiredate, 'YYYY'), 1980 , 'O' )   )  "1980년 사원수"
      , COUNT(  DECODE( TO_CHAR( hiredate, 'YYYY'), 1981 , 'O' )   )  "1981년 사원수"
      , COUNT(  DECODE( TO_CHAR( hiredate, 'YYYY'), 1982 , 'O' )   )  "1982년 사원수"
   FROM emp;
   
   3) PIVOT()
   SELECT *
   FROM (
            SELECT TO_CHAR( hiredate, 'YYYY') hire_year
            FROM emp
         )
   PIVOT( COUNT( hire_year )  FOR hire_year IN ( 1980, 1981, 1982 ));      
   
   --
   SELECT DISTINCT TO_CHAR( hiredate, 'YYYY') hire_year
   FROM emp;
   -- PIVOT()     IN (목록 서브쿼리 사용할 수 없다. ) X
   SELECT *
   FROM (
            SELECT TO_CHAR( hiredate, 'YYYY') hire_year
            FROM emp
         )
   PIVOT( COUNT( hire_year )  FOR hire_year IN ( SELECT DISTINCT TO_CHAR( hiredate, 'YYYY') hire_year   FROM emp )); 
   
--------------------------------------------------------------------------------   
-- [ ROLLUP 절과 CUBE 절 ]
   ㄴ GROUP BY절에서 사용되어 그룹별 소계를 추가로 보여주는 역할을 한다. 
   ㄴ  즉, 추가적인 집계 정보를 보여준다 .
 예) insa 테이블에서 남자사원수, 여자사원수를 조회  + 총사원수
   SELECT 
      CASE MOD(SUBSTR( ssn , -7, 1), 2)
         WHEN 1 THEN '남자'
         ELSE  '여자'
      END  gender
      , COUNT(*) 사원수
   FROM insa
   GROUP BY  MOD(SUBSTR( ssn , -7, 1), 2)
   UNION ALL
   SELECT '', COUNT(*) 
   FROM insa;
 
    -- GROUP BY + ROLLUP  사용..
    SELECT 
      CASE MOD(SUBSTR( ssn , -7, 1), 2)
         WHEN 1 THEN '남자'
         --ELSE  '여자'
         WHEN 0 THEN '여자'
      END  gender
      , COUNT(*) 사원수
   FROM insa
   GROUP BY ROLLUP( MOD(SUBSTR( ssn , -7, 1), 2) );
   
  -- 예) ROLLUP, CUBE 차이점 체크
  -- insa 테이블에서 부서별 1차 그룹핑
  --                  ㄴ 직급별 2차 그룹핑
  SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  GROUP BY buseo, jikwi
  ORDER BY buseo, jikwi;
  --  1) 각 부서별 사원수 추가 조회   
  SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  GROUP BY buseo, jikwi
  ORDER BY buseo, jikwi;SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  GROUP BY buseo, jikwi
  ORDER BY buseo, jikwi;
  -- 2)
  SELECT buseo, COUNT(*) 부서원수
  FROM insa
  GROUP BY buseo;
  -- 1) + 2) 출력.
  SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  GROUP BY buseo, jikwi  
  UNION ALL
  SELECT buseo, '' ,  COUNT(*) 부서원수
  FROM insa
  GROUP BY buseo
  UNION ALL
  SELECT '' ,'' , COUNT(*)
  FROM insa
  UNION ALL
  SELECT '' ,jikwi , COUNT(*)
  FROM insa
  GROUP BY jikwi
  
  --ORDER BY buseo, jikwi  ;
  -- ROLLUP 절 사용.
  SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  GROUP BY CUBE( buseo, jikwi )
  -- GROUP BY ROLLUP( buseo, jikwi )
  ORDER BY buseo, jikwi;
   

  -- 분할( parial) ROLLUP  
  SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  -- GROUP BY CUBE( buseo, jikwi )
  -- GROUP BY  buseo, ROLLUP(jikwi )  -- 전체사원수 60 X
  GROUP BY ROLLUP( buseo), jikwi   -- 전체사원수 60 X, 직위 부분집합 O, 부서 부분집합 X
  ORDER BY buseo, jikwi;
  
  -- 12:05 수업시작~
  -- +5  
  -- GROUPING SETS 함수GROUPING SETS 함수
  
  SELECT buseo , '' , COUNT(*)
  FROM insa
  GROUP BY buseo 
  UNION ALL
  SELECT '', jikwi , COUNT(*)
  FROM insa
  GROUP BY jikwi; 
 
   --
  SELECT buseo, jikwi , COUNT(*)
  FROM insa
  GROUP BY  GROUPING SETS( buseo, jikwi )
  ORDER BY buseo, jikwi;

--------------------------------------------------------------------------------
 -- 자바   :  임의의 수(난수)           0.0 <=  Math.random()  < 1.0
 -- 오라클 :  dbms_random 패키지 == 관련 함수, 프로시저 등등
 
 SELECT DBMS_RANDOM.VALUE   -- JAVA Math.random()
      , TRUNC( DBMS_RANDOM.VALUE(0,101) ) --  0<=   <101
      , FLOOR( DBMS_RANDOM.VALUE(0,101) ) --  0<=   <101
      , FLOOR(DBMS_RANDOM.VALUE(0, 45 )) + 1  -- 1<= <=45
      , DBMS_RANDOM.STRING('U', 5 ) -- 대문자 5개
      , DBMS_RANDOM.STRING('L', 5 ) -- 소문자 5개
      , DBMS_RANDOM.STRING('A', 5 ) -- 대소문자 5개
      , DBMS_RANDOM.STRING('', 5 ) -- 대소문자 5개 + 특수문자
 FROM dual;
 
 [문제] SMS 인증번호 숫자 6자리
    DBMS_RANDOM.VALUE 함수를 사용해서 
    
   SELECT 
       TRUNC( DBMS_RANDOM.VALUE( 100000 , 1000000 ) )  -- 100000 <=   <= 999999
       ,  LPAD(FLOOR(DBMS_RANDOM.VALUE(0, 1000000)), 6, '0') -- 1 <= 숫자 <=45
   FROM dual;
 
 -- [ 오라클 자료형 ( Data Type ))  정리 ]
 1) CHAR
   ㄱ) "고정길이" 문자 스트링에 사용된다.   <->      "가변길이" 
     예) 주민등록번호 저장 -> 모든 사람들이 14자리
   ㄴ. ['a']['b']['c']['']['']['']['']['']  
   ㄷ. [][][]  abcd 에러 발생
   ㄹ. DB 설정에 따라 1문자 1~4바이트 처리.
   ㅁ. 형식
     CHAR(SIZE [byte] | char])
     최대 2000바이트 문자를 저장한다.   
     
     예)   CHAR        == CHAR(1 BYTE) == CHAR(1)
           CHAR(3)     == CHAR(3 BYTE)
           CHAR(3 BYTE) -- 3바이트
           CHAR(3 CHAR) -- 3문자 
    ㅂ. 
      CREATE TABLE tbl_char (
         -- 컬럼명 자료형([크기])
          aa CHAR   -- CHAR(1) == CHAR(1 BYTE)
        , bb CHAR(3) -- CHAR(3 BYTE) 알파벳 3문자, 한글 1문자
        , cc CHAR(3 CHAR)
      ); 
     -- Table TBL_CHAR이(가) 생성되었습니다.
     SELECT *
     FROM tbl_char;
     --
     INSERT INTO tbl_char ( aa, bb, cc ) VALUES ( 'A','ABC','abc') ;
     COMMIT;
     INSERT INTO tbl_char ( aa, bb, cc ) VALUES ( '한','ABC','abc') ;
     -- ORA-12899: value too large for column "SCOTT"."TBL_CHAR"."AA" (actual: 3, maximum: 1)     
     INSERT INTO tbl_char ( aa, bb, cc ) VALUES ( '1','홍길','abc') ;
     
     INSERT INTO tbl_char ( aa, bb, cc ) VALUES ( '1','MBC','홍길동') ;
     INSERT INTO tbl_char ( aa, bb, cc ) VALUES ( '1','MBC','abc') ;
     --
     SELECT VSIZE('A'), VSIZE('한')
     FROM dual;
     COMMIT;
     --
     DROP TABLE tbl_char ;
     -- Table TBL_CHAR이(가) 삭제되었습니다.
 
    CHAR[( 3 [BYTE] | CHAR )] 고정길이  ['a'][blank][blank] 고정길이, 2000바이트
 2) NCHAR
    U[N]ICODE + CHAR  'A' '홍'  2바이트
    NCHAR(SIZE)
    NCHAR(3) 'abc' / '홍길동'  고정길이, 2000바이트
    NCHAR(1) == NCHAR
    
    고정길이 :  CHAR, NCHAR
      예) 주민등록번호    : CHAR(14 BYTE)
      예) 한글 고정 6자리 : NCHAR(6)
 3) NVARCHAR2(size)   4000 바이트  
 4) VARCHAR2(SIZE BYTE | CHAR )    4000 바잍트
    
      VAR+CHAR2(SIZE BYTE|CHAR) 가변길이
    N+VAR+CHAR2(size) 가변길이
 
   예) CHAR(12)        [a][b][c][blank][][][][][][][][blank]
      VARCHAR2(12 BYTE)[a][b][c]
 
   예) 게시글의 제목 :    CHAR / NCHAR
                      VARCHAR2 / N+VARCHAR2  가변길이 
  DESC EMP;
  ENAME             VARCHAR2(10)
  INSERT INTO emp ( empno , ename ) VALUES ( 9999, '홍길동님')
 
 5) VARCHAR  == VARCHAR2의 시노님
 6) LONG - 가변길이, 2GB 
--    자바 long   정수  -900경~ 900경
  예) 게시판 글 내용
     content LONG
 7)  NUMBER[(p[,s])] 숫자( 정수, 실수 )
    예)  p  : precision  전체 자리수(정밀도)   1~38
         s  : scale        소숫점자리수       -84~127
        NUMBER  ==  NUMBER( 38, 127 )
        NUMBER(3)   정수  == NUMBER(3, 0)
        NUMBER(5,2) 실수
   예) 
    CREATE TABLE tbl_number(
         name NVARCHAR2(10) -- 문자열 char,nchar,varchar,varchar2, nvarchar2, long
       , kor  NUMBER(3)-- NUMBER  0~100 정수   999 ~ -999
       , eng  NUMBER(3)
       , mat  NUMBER(3)
       , tot  NUMBER(3)
       , avg  NUMBER(5,2) -- 100.00
       , r NUMBER(2)  ---  99~99
    );
   -- Table TBL_NUMBER이(가) 생성되었습니다.
   INSERT INTO tbl_number VALUES 
     ( '홍길동', 90, 89, 100, null, null, null );
  INSERT INTO tbl_number VALUES 
     ( '윤재민', 90, 80.12, 78, null, null, null );     
   COMMIT;
   
   INSERT INTO tbl_number VALUES 
     ( '탁인혁', 90, 20, 78, null, null, null );     
  ROLLBACK;  
   
   -- 총점, 평균 계산 UPDATE
   UPDATE tbl_number
   SET  tot = kor+eng+mat , avg = ( kor +eng +mat)/3;
   -- WHERE
   COMMIT;
   
   [문제] R 등수 null  처리 UPDATE
   
   SELECT tot
      , ( SELECT COUNT(*) +1 FROM tbl_number WHERE tot > t1.tot ) r
   FROM tbl_number t1;
   
   -- 모든 학생들 등수 처리..
   UPDATE tbl_number t1
   SET r = ( SELECT COUNT(*) +1 FROM tbl_number WHERE tot > t1.tot );
   -- WHERE;
   COMMIT;
   
   SELECT  *
   FROM tbl_number;  
   
   ROLLBACK;

   3:01 수업 시작~~~ 
   
실제 데이터

NUMBER 선언

저장되는 값

123.89 NUMBER 123.89 
123.89 NUMBER(3) 124 
123.89 NUMBER(3,2) precision을 초과 
123.89 NUMBER(4,2) precision을 초과 
123.89 NUMBER(5,2) 123.89 
123.89 NUMBER(6,1) 123.9 
123.89 NUMBER(6,-2) 100 
.01234 NUMBER(4,5) .01234 
.00012 NUMBER(4,5) .00012 
.000127 NUMBER(4,5) .00013 
.0000012 NUMBER(2,7) .0000012 
.00000123 NUMBER(2,7) .0000012 
1.2e-4 NUMBER(2,5) 0.00012 
1.2e-5 NUMBER(2,5) 0.00001 

DESC emp;
DESC dept;
DESC salgrade;
DESC bonus;

 8) FLOAT(p) == 내부적으로는 NUMBER 처리된다. 
 9) DATE 
    ㄴ 날짜, 시간
    ㄴ 고정 길이   7 byte 저장.
    
    TIMESTAMP[(n)] == TIMESTAMP(6)
       00:00:00.000000000      나노세컨드 
    
    SELECT SYSDATE -- '23/03/23'    
    FROM dual;
    
    SELECT hiredate  -- 80/12/17
     , TO_CHAR( hiredate, 'TS')
    FROM emp;
   
   예) 게시판 작성일   : DATE O , TIMESTAMP X

 10) RAW(size)   2진데이터( 0,1 ) 2000바이트
     LONGRAW                     2GB
     
     RAW == 가공하지 않은 , 날것,    
     홍길동.gif  이미지파일 -> TABLE 저장
     01010111                          01010111   
    게시판 글 쓰기 + (첨부파일*3개)      특정 폴더  : 첨부파일 저장하고
                                      TABLE : 저장된 파일의 경로만 저장.
   
 11) BFILE    2진데이터 (0,1) , 외부 파일 형태로 저장
 
 12) LOB = [L]arge [OB]ject
        B   + LOB    = Binary(2진 데이터)
        C   + LOB    = Char
        NC  + LOB    = NChar
 
       게시판 글 내용(CONTENT )  CLOB/LONG/NVARCHAR2(2000)
   
 13) ROWID
     ROW(행) + ID(고유한값)
     SELECT ROWID, emp.*
     FROM emp;
--------------------------------------------------------------------------------

  오라클 문자 : char, nchar, varchar, varchar2, nvarchar2
               long, clob
       숫자 : number(p,s)   , float
       날짜 : date, timestamp
       
      이진데이터 :  RAW/LONGRAW , BFILE  , BLOB    
      LOB : blob, clob, nclob
      
--------------------------------------------------------------------------------
-- [ COUNT 함수 ]
    ㄴ 쿼리한 행의 수를 반환한다.
    ㄴ COUNT(컬럼명) 함수는 NULL이 아닌 행의 수를 출력하고 
       COUNT(*) 함수는 NULL을 포함한 행의 수를 출력한다.
   【형식】
COUNT([* ¦ DISTINCT ¦ ALL] 컬럼명) [ [OVER] (analytic 절)]
   --  
   SELECT COUNT( DISTINCT buseo  )
   FROM insa;
   --  ORA-00937: not a single-group group function
   -- 복수행 함수 이기에  name, basicpay랑 같이 사용 X
   SELECT name, basicpay
    -- OVER절을 사용하면 누적된 수를 카운팅한다. 
          , COUNT(*) OVER( ORDER BY basicpay ASC )
   FROM insa;
   
   -- 부서로 그룹핑한 후 누적된 수를 조회...
    SELECT name, basicpay , buseo
          , COUNT(*) OVER( PARTITION BY buseo  ORDER BY basicpay ASC )
   FROM insa;
 
   -- SUM()
   -- basicpay의 누적된 합을 조회
   SELECT name, basicpay 
          , SUM(basicpay) OVER( ORDER BY basicpay ASC )
   FROM insa;
   
   -- 부서로 그룹핑한 후 누적된 수를 조회...
    SELECT name, basicpay , buseo
          , SUM(basicpay) OVER( PARTITION BY buseo  ORDER BY basicpay ASC )
   FROM insa;
 
   -- AVG()
   -- basicpay의 누적된 평균을 조회
   SELECT name, basicpay 
          , AVG(basicpay) OVER( ORDER BY basicpay ASC )
   FROM insa;
   
   -- 부서로 그룹핑한 후 누적된 평균를 조회...
    SELECT name, basicpay , buseo
          , AVG(basicpay) OVER( PARTITION BY buseo  ORDER BY basicpay ASC )
   FROM insa;

--------------------------------------------------------------------------------
4:03 수업 시작~~ 
테이블 생성/수정/삭제  CRUD  ~  + 제약조건
--------------------------------------------------------------------------------
[데이터 저장] - CRUD = 테이블(table)
***[ DB 모델링 ] ***
요구분석 -> 개념적 모델링 -> 논리적 모델링 -> 물리적모델링
                                         [오라클] 테이블생성
                                         MySQL
                                           ;
-- [회원정보]를 관리하는 테이블 생성 : 회원테이블
 컬럼명(열)  물리적컬럼명    자료형      크기        필수입력                주석
 아이디       id           VARCHAR2   10 BYTE    NOT NULL  PRIMARY KEY
 이름         name        NVARCHAR2   10 문자    NOT NULL  
 나이         age         NUMBER      3             
 전화번호      tel         CHAR        13        NOT NULL
                          010-1234-1234
 생일         birth        DATE
 기타         etc         NVARCHAR2   200
                           LONG  2GB
                           CLOB
                          
  :
  :
 재무상태(연봉,부..)
 회사/직급/연봉

-- 테이블 생성
【형식】
CREATE TABLE 테이블명
(컬럼명 데이터타입 [, 컬럼명 데이터타입]...)
[TABLESPACE tablespace명]
[PCTFREE 정수]
[PCTUSED 정수]
[INITRANS 정수]
[MAXTRANS 정수]
[STORAGE storage절]
[LOGGING ¦ NOLOGGING]
[CACHE ¦ NOCACHE];



SELECT *
FROM emp;
-- 테이블 생성( 가장 단순한 방법 )
【형식】
    CREATE [GLOBAL TEMPORARY] TABLE [schema.] table {relational_table ¦ 
                                                     object_table ¦
                                                     XML_Type_table}

【relational_table의 형식】
   [(relational_properties) [ON COMMIT {DELETE ¦ PRESERVE} ROWS]
   [physical_properties] [table_properties];

【object_table의 형식】
   OF [schema.]object_type [object_table_substitution]
    [(object_properties) [ON COMMIT {DELETE ¦ PRESERVE} ROWS]
    [OID_clause] [OID_index_clause] [physical_properties] [table_properties];

【XMP_Type_table의 형식】
   OF XMLTYPE [(object_properties) [XMLTYPE XML_Type_storage] [XML_Schema_spec]
    [XML_Type_virtual_columns] [ON COMMIT {DELETE ¦ PRESERVE} ROWS]
    [OID_clause] [OID_index_clause] [physical_properities] [table_properities]

이 문을 실행하려면 자신의 스키마에서는 CREATE TABLE 시스템권한이 있어야 하고
    다른 사용자 스키마내에서 테이블을 생성하려면 CREATE ANY TABLE 시스템권한이 있어야 하며,
    테이블스페이스를 위해서 UNLIMITED TABLE 시스템권한이 있어야 한다.

【간단한형식】
    CREATE [GLOBAL TEMPORARY] TABLE [schema.] table
      ( 
        열이름  데이터타입 [DEFAULT 표현식] [제약조건] 
       [,열이름  데이터타입 [DEFAULT 표현식] [제약조건] ] 
       [,...]  
      ); 
  실습)
 
            
 
 
 기타         etc         NVARCHAR2   200
 
  CREATE TABLE  scott.tbl_member
  (
       id   VARCHAR2(10) NOT NULL PRIMARY KEY
     , name  NVARCHAR2(10)  NOT NULL
     , age   NUMBER(3)
     , tel   CHAR(13) NOT NULL
     , birth DATE
     , etc   NVARCHAR2(200)
  );
 -- Table SCOTT.TBL_MEMBER이(가) 생성되었습니다.
 1) 생성된 테이블 확인
 SELECT *
 FROM  tabs  -- user_tables
 WHERE REGEXP_LIKE(  table_name ,  'member' , 'i');
 WHERE table_name LIKE '%MEMBER%';

 2) 테이블 삭제.
 
 【형식】
     DROP TABLE [schema.]table [CASCADE CONSTRAINTS] [PURGE];
  PURGE(퍼지) : 사전적의지  깨끗이하다, 제거하다. 
  DROP TABLE scott.tbl_member PURGE;


-- HR --
    
SELECT TO_CHAR( TO_DATE('2022.01.03'), 'IW' ) -- ISO 표준 주   월~일까지 1주.
, TO_CHAR( TO_DATE('2022.01.09'), 'IW' )
 , TO_CHAR( TO_DATE('2022.02.04'), 'WW' )  -- 년의 주          1~7  끝어짐
 , TO_CHAR( TO_DATE('2022.02.05'), 'WW' )
FROM dual;

               
   -- SCOTT --

--------------------------------------------------------------------------------
-- 복습문제 
--------------------------------------------------------------------------------

  [실행결과]
       CLERK   SALESMAN  PRESIDENT    MANAGER    ANALYST
---------- ---------- ---------- ---------- ----------
         3          4          1          3          1

--1) GROUP BY job       + COUNT(*) 사용
        SELECT job, COUNT(*) "사원수"
        FROM emp
        GROUP BY job;

--2) 가로 출력
        SELECT
            COUNT (DECODE( job, 'CLERK', 1) ) CLERK
            ,COUNT (DECODE( job, 'SALESMAN', 1) ) SALESMAN
            ,COUNT (DECODE( job, 'PRESIDENT', 1) ) PRESIDENT
            ,COUNT (DECODE( job, 'MANAGER', 1) ) MANAGER
            ,COUNT (DECODE( job, 'ANALYST', 1) ) ANALYST
        FROM emp;


--[피봇 (PIVOT) / 언피봇(UNPIVOT) 함수]
    1. 오라클 11g부터 제공하는 함수
    2. 행과 열을 뒤집는 함수
    3. [형식]
        SELECT * 
        FROM (피벗 대상 쿼리문) -- 1. 서버쿼리(세로를 가로로 만들기)
        PIVOT (그룹함수(집계컬럼) FOR 피벗컬럼(대상) IN(피벗컬럼 값 AS 별칭...))
    4.  순서는
        1)피벗 대상 쿼리문
        2) IN(목록)
        3) FOR 피벗컬럼
        4) 그룹함수(집게컬럼)

        1) SELECT job FROM emp;
        2) IN(목록)
        3) FOR 피벗컬럼
        4) 그룹함수(집게컬럼)

    예)
        SELECT *
        FROM (
                SELECT job 
                FROM emp
              ) 
        PIVOT (COUNT(job) FOR job IN('CLERK', 'SALESMAN', 'PRESIDENT', 'MANAGER', 'ANALYST' ))









2. emp 테이블에서  [JOB별로] 각 월별 입사한 사원의 수를 조회 



  ㄱ. COUNT(), DECODE() 사용
  
  

  
  

JOB         COUNT(*)         1월         2월         3월         4월         5월         6월         7월         8월         9월        10월        11월        12월
--------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
CLERK              3          1          0          0          0          0          0          0          0          0          0          0          2
SALESMAN           4          0          2          0          0          0          0          0          0          2          0          0          0
PRESIDENT          1          0          0          0          0          0          0          0          0          0          0          1          0
MANAGER            3          0          0          0          1          1          1          0          0          0          0          0          0
ANALYST            1          0          0          0          0          0          0          0          0          0          0          0          1

SELECT job, COUNT(*)
    , COUNT(decode( to_char(hiredate, 'MM'), '01', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '02', 'O')) "02월"
    , count(decode( to_char(hiredate, 'mm'), '03', 'O')) "03월"
    , count(decode( to_char(hiredate, 'mm'), '04', 'O')) "04월"
    , count(decode( to_char(hiredate, 'mm'), '05', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '06', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '07', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '08', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '09', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '10', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '11', 'O')) "01월"
    , count(decode( to_char(hiredate, 'mm'), '12', 'O')) "12월"
FROM emp
GROUP BY JOB;


SELECT job, EXTRACT( MONTH FROM hiredate) 월 , COUNT(*) 인원수
FROM emp
GROUP BY job, EXTRACT( MONTH FROM hiredate)
ORDER BY job, 월



  ㄴ. GROUP BY 절 사용

         월        인원수
---------- ----------
         1          1
         2          2
         4          1
         5          1
         6          1
         9          2
        11          1
        12          3

8개 행이 선택되었습니다. 

--1)
SELECT TO_NUMBER(TO_CHAR( hiredate, 'MM' ) )월, COUNT(*) 인원수
FROM emp
GROUP BY TO_NUMBER(TO_CHAR(hiredate, 'MM' ) )
ORDER BY TO_NUMBER(TO_CHAR(hiredate, 'MM' ) );

--2) EXTRACT
SELECT EXTRACT( MONTH FROM hiredate)월, COUNT(*) 인원수
FROM emp
GROUP BY EXTRACT( MONTH FROM hiredate)
ORDER BY 월;


 [문제]   피봇함수를 사용해서 아래와 같이 출력.
 JOB               1월          2          3          4          5          6          7          8          9         10         11         12
--------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
CLERK              1          0          0          0          0          0          0          0          0          0          0          2
SALESMAN           0          2          0          0          0          0          0          0          2          0          0          0
PRESIDENT          0          0          0          0          0          0          0          0          0          0          1          0
MANAGER            0          0          0          1          1          1          0          0          0          0          0          0
ANALYST            0          0          0          0          0          0          0          0          0          0  
    1) 피봇 대상 쿼리
      SELECT EXTRACT( MONTH FROM hiredate )  hire_month 
      FROM emp;
    2) IN ( 목록 )
       1,2,3,4,5,6,7,8,9, 10, 11, 12
    3) FOR 피봇 컬럼
          hire_month
    4) 집계함수(컬럼 ))
       COUNT( hire_month )
        -- 전체 사원들이 입사한 월별 사원수 파악
        SELECT *
        FROM (
                SELECT EXTRACT( MONTH FROM hiredate )  hire_month 
                FROM emp
              ) 
        PIVOT (COUNT(hire_month ) FOR hire_month  IN(1,2,3,4,5,6,7,8,9, 10, 11, 12 ));
        
        -- 전체 사원들이 입사한 월별 사원수 파악
        SELECT *
        FROM (
                SELECT  job,  EXTRACT( MONTH FROM hiredate )  hire_month 
                FROM emp
              ) 
        PIVOT (COUNT(hire_month ) FOR hire_month  IN(1 AS "1월",2,3,4,5,6,7,8,9, 10, 11, 12 ));
    
    -- [ UNPIVOT() 정리 ]

3. emp 테이블에서 각 부서별 급여 많이 받는 사원 2명씩 출력
  실행결과)
       SEQ      EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- ---------- --------- ---------- -------- ---------- ---------- ----------
         1       7839 KING       PRESIDENT            81/11/17       5000                    10
         2       7782 CLARK      MANAGER         7839 81/06/09       2450                    10
         1       7902 FORD       ANALYST         7566 81/12/03       3000                    20
         2       7566 JONES      MANAGER         7839 81/04/02       2975                    20
         1       7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
         2       7654 MARTIN     SALESMAN        7698 81/09/28       1250       1400         30
   -- 1) TOP-N 방식
   -- 2) RANK 함수 
   SELECT t.*
   FROM (
       SELECT empno, ename, job, mgr, hiredate, sal , comm, deptno
           , RANK() OVER(  PARTITION BY deptno ORDER BY  sal + NVL(comm, 0)  ) SEQ
       FROM emp
   ) t
   WHERE seq <= 2;    
--------------------------------------------------------------------------------   
[피봇문제 1] emp 테이블에서 
                  1등급  2등급 ... 5등급
                  2     3          1
   -- 등급) salgrade 테이블  - grade, losal, hisal  + emp 테이블 조인
   --            부모,자식테이블 관계 X
   --            NON EQUI JOIN      조건   BETWEEN ~ AND 연산자
   SELECT empno, ename, sal , grade
   FROM emp e JOIN salgrade s  ON e.sal BETWEEN s.losal AND s.hisal;
    -- 각 sal등급의 인원수 몇 명인지 조회 ? 
    1) GROUP BY
    
    SELECT grade || '등급' , COUNT(*) 사원수
    FROM (
         SELECT empno, ename, sal , grade
         FROM emp e JOIN salgrade s  ON e.sal BETWEEN s.losal AND s.hisal
    ) t
    GROUP BY grade
    ORDER BY grade ASC;
    
    2) COUNT() + DECODE()
    
    SELECT 
          COUNT(  DECODE( grade, 1 , 'O'  ) ) "1등급"
        , COUNT(  DECODE( grade, 2 , 'O'  ) ) "2등급"
        , COUNT(  DECODE( grade, 3 , 'O'  ) ) "3등급"
        , COUNT(  DECODE( grade, 4 , 'O'  ) ) "4등급"
        , COUNT(  DECODE( grade, 5 , 'O'  ) ) "5등급"
    FROM (
         SELECT empno, ename, sal , grade
         FROM emp e JOIN salgrade s  ON e.sal BETWEEN s.losal AND s.hisal
    ) t;
    
    3) PIVOT()
       (1) 피봇대상
       SELECT *
       FROM ( 
            SELECT grade
            FROM emp e JOIN salgrade s  ON e.sal BETWEEN s.losal AND s.hisal
       )
       PIVOT( COUNT(grade) FOR grade IN ( 1 AS "1등급", 2, 3, 4, 5 ) );
    
   11:00 수업 시작~ 
[피봇문제 2] emp 테이블에서 년도별 입사사원수를 조회
         ( 1980, 1981, 1982 )
    SELECT DISTINCT TO_CHAR( hiredate, 'YYYY') YEAR
    FROM emp;

   1) GROUP BY
    SELECT TO_CHAR( hiredate, 'YYYY') HIRE_YEAR, COUNT(*) 사원수
    FROM emp
    GROUP BY TO_CHAR( hiredate, 'YYYY')
    ORDER BY HIRE_YEAR;
   
   2) COUNT(), DECODE()
   SELECT 
      COUNT(  DECODE( TO_CHAR( hiredate, 'YYYY'), 1980 , 'O' )   )  "1980년 사원수"
      , COUNT(  DECODE( TO_CHAR( hiredate, 'YYYY'), 1981 , 'O' )   )  "1981년 사원수"
      , COUNT(  DECODE( TO_CHAR( hiredate, 'YYYY'), 1982 , 'O' )   )  "1982년 사원수"
   FROM emp;
   
   3) PIVOT()
   SELECT *
   FROM (
            SELECT TO_CHAR( hiredate, 'YYYY') hire_year
            FROM emp
         )
   PIVOT( COUNT( hire_year )  FOR hire_year IN ( 1980, 1981, 1982 ));      
   
   --
   SELECT DISTINCT TO_CHAR( hiredate, 'YYYY') hire_year
   FROM emp;
   -- PIVOT()     IN (목록 서브쿼리 사용할 수 없다. ) X
   SELECT *
   FROM (
            SELECT TO_CHAR( hiredate, 'YYYY') hire_year
            FROM emp
         )
   PIVOT( COUNT( hire_year )  FOR hire_year IN ( SELECT DISTINCT TO_CHAR( hiredate, 'YYYY') hire_year   FROM emp )); 
   
--------------------------------------------------------------------------------   
-- [ ROLLUP 절과 CUBE 절 ]
   ㄴ GROUP BY절에서 사용되어 그룹별 소계를 추가로 보여주는 역할을 한다. 
   ㄴ  즉, 추가적인 집계 정보를 보여준다 .
 예) insa 테이블에서 남자사원수, 여자사원수를 조회  + 총사원수
   SELECT 
      CASE MOD(SUBSTR( ssn , -7, 1), 2)
         WHEN 1 THEN '남자'
         ELSE  '여자'
      END  gender
      , COUNT(*) 사원수
   FROM insa
   GROUP BY  MOD(SUBSTR( ssn , -7, 1), 2)
   UNION ALL
   SELECT '', COUNT(*) 
   FROM insa;
 
    -- GROUP BY + ROLLUP  사용..
    SELECT 
      CASE MOD(SUBSTR( ssn , -7, 1), 2)
         WHEN 1 THEN '남자'
         --ELSE  '여자'
         WHEN 0 THEN '여자'
      END  gender
      , COUNT(*) 사원수
   FROM insa
   GROUP BY ROLLUP( MOD(SUBSTR( ssn , -7, 1), 2) );
   
  -- 예) ROLLUP, CUBE 차이점 체크
  -- insa 테이블에서 부서별 1차 그룹핑
  --                  ㄴ 직급별 2차 그룹핑
  SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  GROUP BY buseo, jikwi
  ORDER BY buseo, jikwi;
  --  1) 각 부서별 사원수 추가 조회   
  SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  GROUP BY buseo, jikwi
  ORDER BY buseo, jikwi;SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  GROUP BY buseo, jikwi
  ORDER BY buseo, jikwi;
  -- 2)
  SELECT buseo, COUNT(*) 부서원수
  FROM insa
  GROUP BY buseo;
  -- 1) + 2) 출력.
  SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  GROUP BY buseo, jikwi  
  UNION ALL
  SELECT buseo, '' ,  COUNT(*) 부서원수
  FROM insa
  GROUP BY buseo
  UNION ALL
  SELECT '' ,'' , COUNT(*)
  FROM insa
  UNION ALL
  SELECT '' ,jikwi , COUNT(*)
  FROM insa
  GROUP BY jikwi
  
  --ORDER BY buseo, jikwi  ;
  -- ROLLUP 절 사용.
  SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  GROUP BY CUBE( buseo, jikwi )
  -- GROUP BY ROLLUP( buseo, jikwi )
  ORDER BY buseo, jikwi;
   

  -- 분할( parial) ROLLUP  
  SELECT buseo, jikwi, COUNT(*) 사원수
  FROM insa
  -- GROUP BY CUBE( buseo, jikwi )
  -- GROUP BY  buseo, ROLLUP(jikwi )  -- 전체사원수 60 X
  GROUP BY ROLLUP( buseo), jikwi   -- 전체사원수 60 X, 직위 부분집합 O, 부서 부분집합 X
  ORDER BY buseo, jikwi;
  
  -- 12:05 수업시작~
  -- +5  
  -- GROUPING SETS 함수GROUPING SETS 함수
  
  SELECT buseo , '' , COUNT(*)
  FROM insa
  GROUP BY buseo 
  UNION ALL
  SELECT '', jikwi , COUNT(*)
  FROM insa
  GROUP BY jikwi; 
 
   --
  SELECT buseo, jikwi , COUNT(*)
  FROM insa
  GROUP BY  GROUPING SETS( buseo, jikwi )
  ORDER BY buseo, jikwi;

--------------------------------------------------------------------------------
 -- 자바   :  임의의 수(난수)           0.0 <=  Math.random()  < 1.0
 -- 오라클 :  dbms_random 패키지 == 관련 함수, 프로시저 등등
 
 SELECT DBMS_RANDOM.VALUE   -- JAVA Math.random()
      , TRUNC( DBMS_RANDOM.VALUE(0,101) ) --  0<=   <101
      , FLOOR( DBMS_RANDOM.VALUE(0,101) ) --  0<=   <101
      , FLOOR(DBMS_RANDOM.VALUE(0, 45 )) + 1  -- 1<= <=45
      , DBMS_RANDOM.STRING('U', 5 ) -- 대문자 5개
      , DBMS_RANDOM.STRING('L', 5 ) -- 소문자 5개
      , DBMS_RANDOM.STRING('A', 5 ) -- 대소문자 5개
      , DBMS_RANDOM.STRING('', 5 ) -- 대소문자 5개 + 특수문자
 FROM dual;
 
 [문제] SMS 인증번호 숫자 6자리
    DBMS_RANDOM.VALUE 함수를 사용해서 
    
   SELECT 
       TRUNC( DBMS_RANDOM.VALUE( 100000 , 1000000 ) )  -- 100000 <=   <= 999999
       ,  LPAD(FLOOR(DBMS_RANDOM.VALUE(0, 1000000)), 6, '0') -- 1 <= 숫자 <=45
   FROM dual;
 
 -- [ 오라클 자료형 ( Data Type ))  정리 ]
 1) CHAR
   ㄱ) "고정길이" 문자 스트링에 사용된다.   <->      "가변길이" 
     예) 주민등록번호 저장 -> 모든 사람들이 14자리
   ㄴ. ['a']['b']['c']['']['']['']['']['']  
   ㄷ. [][][]  abcd 에러 발생
   ㄹ. DB 설정에 따라 1문자 1~4바이트 처리.
   ㅁ. 형식
     CHAR(SIZE [byte] | char])
     최대 2000바이트 문자를 저장한다.   
     
     예)   CHAR        == CHAR(1 BYTE) == CHAR(1)
           CHAR(3)     == CHAR(3 BYTE)
           CHAR(3 BYTE) -- 3바이트
           CHAR(3 CHAR) -- 3문자 
    ㅂ. 
      CREATE TABLE tbl_char (
         -- 컬럼명 자료형([크기])
          aa CHAR   -- CHAR(1) == CHAR(1 BYTE)
        , bb CHAR(3) -- CHAR(3 BYTE) 알파벳 3문자, 한글 1문자
        , cc CHAR(3 CHAR)
      ); 
     -- Table TBL_CHAR이(가) 생성되었습니다.
     SELECT *
     FROM tbl_char;
     --
     INSERT INTO tbl_char ( aa, bb, cc ) VALUES ( 'A','ABC','abc') ;
     COMMIT;
     INSERT INTO tbl_char ( aa, bb, cc ) VALUES ( '한','ABC','abc') ;
     -- ORA-12899: value too large for column "SCOTT"."TBL_CHAR"."AA" (actual: 3, maximum: 1)     
     INSERT INTO tbl_char ( aa, bb, cc ) VALUES ( '1','홍길','abc') ;
     
     INSERT INTO tbl_char ( aa, bb, cc ) VALUES ( '1','MBC','홍길동') ;
     INSERT INTO tbl_char ( aa, bb, cc ) VALUES ( '1','MBC','abc') ;
     --
     SELECT VSIZE('A'), VSIZE('한')
     FROM dual;
     COMMIT;
     --
     DROP TABLE tbl_char ;
     -- Table TBL_CHAR이(가) 삭제되었습니다.
 
    CHAR[( 3 [BYTE] | CHAR )] 고정길이  ['a'][blank][blank] 고정길이, 2000바이트
 2) NCHAR
    U[N]ICODE + CHAR  'A' '홍'  2바이트
    NCHAR(SIZE)
    NCHAR(3) 'abc' / '홍길동'  고정길이, 2000바이트
    NCHAR(1) == NCHAR
    
    고정길이 :  CHAR, NCHAR
      예) 주민등록번호    : CHAR(14 BYTE)
      예) 한글 고정 6자리 : NCHAR(6)
 3) NVARCHAR2(size)   4000 바이트  
 4) VARCHAR2(SIZE BYTE | CHAR )    4000 바잍트
    
      VAR+CHAR2(SIZE BYTE|CHAR) 가변길이
    N+VAR+CHAR2(size) 가변길이
 
   예) CHAR(12)        [a][b][c][blank][][][][][][][][blank]
      VARCHAR2(12 BYTE)[a][b][c]
 
   예) 게시글의 제목 :    CHAR / NCHAR
                      VARCHAR2 / N+VARCHAR2  가변길이 
  DESC EMP;
  ENAME             VARCHAR2(10)
  INSERT INTO emp ( empno , ename ) VALUES ( 9999, '홍길동님')
 
 5) VARCHAR  == VARCHAR2의 시노님
 6) LONG - 가변길이, 2GB 
--    자바 long   정수  -900경~ 900경
  예) 게시판 글 내용
     content LONG
 7)  NUMBER[(p[,s])] 숫자( 정수, 실수 )
    예)  p  : precision  전체 자리수(정밀도)   1~38
         s  : scale        소숫점자리수       -84~127
        NUMBER  ==  NUMBER( 38, 127 )
        NUMBER(3)   정수  == NUMBER(3, 0)
        NUMBER(5,2) 실수
   예) 
    CREATE TABLE tbl_number(
         name NVARCHAR2(10) -- 문자열 char,nchar,varchar,varchar2, nvarchar2, long
       , kor  NUMBER(3)-- NUMBER  0~100 정수   999 ~ -999
       , eng  NUMBER(3)
       , mat  NUMBER(3)
       , tot  NUMBER(3)
       , avg  NUMBER(5,2) -- 100.00
       , r NUMBER(2)  ---  99~99
    );
   -- Table TBL_NUMBER이(가) 생성되었습니다.
   INSERT INTO tbl_number VALUES 
     ( '홍길동', 90, 89, 100, null, null, null );
  INSERT INTO tbl_number VALUES 
     ( '윤재민', 90, 80.12, 78, null, null, null );     
   COMMIT;
   
   INSERT INTO tbl_number VALUES 
     ( '탁인혁', 90, 20, 78, null, null, null );     
  ROLLBACK;  
   
   -- 총점, 평균 계산 UPDATE
   UPDATE tbl_number
   SET  tot = kor+eng+mat , avg = ( kor +eng +mat)/3;
   -- WHERE
   COMMIT;
   
   [문제] R 등수 null  처리 UPDATE
   
   SELECT tot
      , ( SELECT COUNT(*) +1 FROM tbl_number WHERE tot > t1.tot ) r
   FROM tbl_number t1;
   
   -- 모든 학생들 등수 처리..
   UPDATE tbl_number t1
   SET r = ( SELECT COUNT(*) +1 FROM tbl_number WHERE tot > t1.tot );
   -- WHERE;
   COMMIT;
   
   SELECT  *
   FROM tbl_number;  
   
   ROLLBACK;

   3:01 수업 시작~~~ 
   
실제 데이터

NUMBER 선언

저장되는 값

123.89 NUMBER 123.89 
123.89 NUMBER(3) 124 
123.89 NUMBER(3,2) precision을 초과 
123.89 NUMBER(4,2) precision을 초과 
123.89 NUMBER(5,2) 123.89 
123.89 NUMBER(6,1) 123.9 
123.89 NUMBER(6,-2) 100 
.01234 NUMBER(4,5) .01234 
.00012 NUMBER(4,5) .00012 
.000127 NUMBER(4,5) .00013 
.0000012 NUMBER(2,7) .0000012 
.00000123 NUMBER(2,7) .0000012 
1.2e-4 NUMBER(2,5) 0.00012 
1.2e-5 NUMBER(2,5) 0.00001 

DESC emp;
DESC dept;
DESC salgrade;
DESC bonus;

 8) FLOAT(p) == 내부적으로는 NUMBER 처리된다. 
 9) DATE 
    ㄴ 날짜, 시간
    ㄴ 고정 길이   7 byte 저장.
    
    TIMESTAMP[(n)] == TIMESTAMP(6)
       00:00:00.000000000      나노세컨드 
    
    SELECT SYSDATE -- '23/03/23'    
    FROM dual;
    
    SELECT hiredate  -- 80/12/17
     , TO_CHAR( hiredate, 'TS')
    FROM emp;
   
   예) 게시판 작성일   : DATE O , TIMESTAMP X

 10) RAW(size)   2진데이터( 0,1 ) 2000바이트
     LONGRAW                     2GB
     
     RAW == 가공하지 않은 , 날것,    
     홍길동.gif  이미지파일 -> TABLE 저장
     01010111                          01010111   
    게시판 글 쓰기 + (첨부파일*3개)      특정 폴더  : 첨부파일 저장하고
                                      TABLE : 저장된 파일의 경로만 저장.
   
 11) BFILE    2진데이터 (0,1) , 외부 파일 형태로 저장
 
 12) LOB = [L]arge [OB]ject
        B   + LOB    = Binary(2진 데이터)
        C   + LOB    = Char
        NC  + LOB    = NChar
 
       게시판 글 내용(CONTENT )  CLOB/LONG/NVARCHAR2(2000)
   
 13) ROWID
     ROW(행) + ID(고유한값)
     SELECT ROWID, emp.*
     FROM emp;
--------------------------------------------------------------------------------

  오라클 문자 : char, nchar, varchar, varchar2, nvarchar2
               long, clob
       숫자 : number(p,s)   , float
       날짜 : date, timestamp
       
      이진데이터 :  RAW/LONGRAW , BFILE  , BLOB    
      LOB : blob, clob, nclob
      
--------------------------------------------------------------------------------
-- [ COUNT 함수 ]
    ㄴ 쿼리한 행의 수를 반환한다.
    ㄴ COUNT(컬럼명) 함수는 NULL이 아닌 행의 수를 출력하고 
       COUNT(*) 함수는 NULL을 포함한 행의 수를 출력한다.
   【형식】
COUNT([* ¦ DISTINCT ¦ ALL] 컬럼명) [ [OVER] (analytic 절)]
   --  
   SELECT COUNT( DISTINCT buseo  )
   FROM insa;
   --  ORA-00937: not a single-group group function
   -- 복수행 함수 이기에  name, basicpay랑 같이 사용 X
   SELECT name, basicpay
    -- OVER절을 사용하면 누적된 수를 카운팅한다. 
          , COUNT(*) OVER( ORDER BY basicpay ASC )
   FROM insa;
   
   -- 부서로 그룹핑한 후 누적된 수를 조회...
    SELECT name, basicpay , buseo
          , COUNT(*) OVER( PARTITION BY buseo  ORDER BY basicpay ASC )
   FROM insa;
 
   -- SUM()
   -- basicpay의 누적된 합을 조회
   SELECT name, basicpay 
          , SUM(basicpay) OVER( ORDER BY basicpay ASC )
   FROM insa;
   
   -- 부서로 그룹핑한 후 누적된 수를 조회...
    SELECT name, basicpay , buseo
          , SUM(basicpay) OVER( PARTITION BY buseo  ORDER BY basicpay ASC )
   FROM insa;
 
   -- AVG()
   -- basicpay의 누적된 평균을 조회
   SELECT name, basicpay 
          , AVG(basicpay) OVER( ORDER BY basicpay ASC )
   FROM insa;
   
   -- 부서로 그룹핑한 후 누적된 평균를 조회...
    SELECT name, basicpay , buseo
          , AVG(basicpay) OVER( PARTITION BY buseo  ORDER BY basicpay ASC )
   FROM insa;

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

테이블 생성/수정/삭제  CRUD  ~  + 제약조건
--------------------------------------------------------------------------------
[데이터 저장] - CRUD = 테이블(table)
***[ DB 모델링 ] ***
요구분석 -> 개념적 모델링 -> 논리적 모델링 -> 물리적모델링
                                         [오라클] 테이블생성
                                         MySQL
                                           ;
-- [회원정보]를 관리하는 테이블 생성 : 회원테이블
 컬럼명(열)  물리적컬럼명    자료형      크기        필수입력                주석
 아이디       id           VARCHAR2   10 BYTE    NOT NULL  PRIMARY KEY
 이름         name        NVARCHAR2   10 문자    NOT NULL  
 나이         age         NUMBER      3             
 전화번호      tel         CHAR        13        NOT NULL
                          010-1234-1234
 생일         birth        DATE
 기타         etc         NVARCHAR2   200
                           LONG  2GB
                           CLOB
                          
  :
  :
 재무상태(연봉,부..)
 회사/직급/연봉

-- 테이블 생성
【형식】
CREATE TABLE 테이블명
(컬럼명 데이터타입 [, 컬럼명 데이터타입]...)
[TABLESPACE tablespace명]
[PCTFREE 정수]
[PCTUSED 정수]
[INITRANS 정수]
[MAXTRANS 정수]
[STORAGE storage절]
[LOGGING ¦ NOLOGGING]
[CACHE ¦ NOCACHE];



SELECT *
FROM emp;
-- 테이블 생성( 가장 단순한 방법 )
【형식】
    CREATE [GLOBAL TEMPORARY] TABLE [schema.] table {relational_table ¦ 
                                                     object_table ¦
                                                     XML_Type_table}

【relational_table의 형식】
   [(relational_properties) [ON COMMIT {DELETE ¦ PRESERVE} ROWS]
   [physical_properties] [table_properties];

【object_table의 형식】
   OF [schema.]object_type [object_table_substitution]
    [(object_properties) [ON COMMIT {DELETE ¦ PRESERVE} ROWS]
    [OID_clause] [OID_index_clause] [physical_properties] [table_properties];

【XMP_Type_table의 형식】
   OF XMLTYPE [(object_properties) [XMLTYPE XML_Type_storage] [XML_Schema_spec]
    [XML_Type_virtual_columns] [ON COMMIT {DELETE ¦ PRESERVE} ROWS]
    [OID_clause] [OID_index_clause] [physical_properities] [table_properities]

이 문을 실행하려면 자신의 스키마에서는 CREATE TABLE 시스템권한이 있어야 하고
    다른 사용자 스키마내에서 테이블을 생성하려면 CREATE ANY TABLE 시스템권한이 있어야 하며,
    테이블스페이스를 위해서 UNLIMITED TABLE 시스템권한이 있어야 한다.

【간단한형식】
    CREATE [GLOBAL TEMPORARY] TABLE [schema.] table
      ( 
        열이름  데이터타입 [DEFAULT 표현식] [제약조건] 
       [,열이름  데이터타입 [DEFAULT 표현식] [제약조건] ] 
       [,...]  
      ); 
  실습)
 
            
 
 
 기타         etc         NVARCHAR2   200
 
  CREATE TABLE  scott.tbl_member
  (
       id   VARCHAR2(10) NOT NULL PRIMARY KEY
     , name  NVARCHAR2(10)  NOT NULL
     , age   NUMBER(3)
     , tel   CHAR(13) NOT NULL
     , birth DATE
     , etc   NVARCHAR2(200)
  );
 -- Table SCOTT.TBL_MEMBER이(가) 생성되었습니다.
 1) 생성된 테이블 확인
 SELECT *
 FROM  tabs  -- user_tables
 WHERE REGEXP_LIKE(  table_name ,  'member' , 'i');
 WHERE table_name LIKE '%MEMBER%';

 2) 테이블 삭제.
 
 【형식】
     DROP TABLE [schema.]table [CASCADE CONSTRAINTS] [PURGE];
  PURGE(퍼지) : 사전적의지  깨끗이하다, 제거하다. 
  DROP TABLE scott.tbl_member PURGE;



--  SYS --

 -- FIRST / LAST 함수
SELECT MIN(sal) KEEP ( DENSE_RANK FIRST ORDER BY sal DESC )  "min_pay"
    , MAX(sal) KEEP ( DENSE_RANK LAST ORDER BY sal )  "max_pay"
    , SUM(sal) KEEP ( DENSE_RANK FIRST ORDER BY sal )  "min_pay"
    , AVG(sal) KEEP ( DENSE_RANK LAST ORDER BY sal )  "max_pay"
FROM emp;

-- 조민경 --
SELECT d.deptno
    , COUNT(e.deptno) 부서원수
FROM emp e RIGHT OUTER JOIN dept d ON e.deptno = d.deptno 
GROUP BY d.deptno
ORDER BY d.deptno ASC;
--
SELECT b.buseo, a.jikwi, nvl(b.cnt,0)
FROM (SELECT DISTINCT jikwi from INSA) a left join (SELECT buseo, jikwi, COUNT(jikwi) cnt 
                                                    FROM insa
                                                    GROUP BY buseo, jikwi) b 
PARTITION BY (b.buseo) on a.jikwi = b.jikwi                                
order by buseo, jikwi;

--참고사이트 :   
--https://blog.naver.com/pino93/222708884741
--https://blog.naver.com/blacksmail/222349045230
--https://jungmina.com/858

ORACLE 10g  PARTITION OUTER JOIN 
   
         
             
 
 
 
 
 
 
 

   
         

  

'-java spring notes- > db' 카테고리의 다른 글

관계를 맺자! 조인  (18) 2023.03.24
오라클 day7~day8  (0) 2023.03.22
오라클 2 -데이터 베이스 객체  (1) 2023.03.21
1오라클 - 오라클 이란?  (1) 2023.03.20
postgres실습,docker  (1) 2023.01.21
profile

냥코딩쟝

@yejang

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!