본문 바로가기

programming/Gukbi

국비 교육 35일차 - GROUP BY, ORDER BY, JOIN

728x90
반응형

오라클에서도 이제 기초 과정에서 심화 과정인 JOIN을 배웠다. 물론 기초 단계인 GROUP BY,  ORDER BY도 오전에 정리하고 시작했다. 

 

아 집합함수도 배웠다. 

 

그러면 먼저 집합함수 &  GROUP BY,  ORDER BY 부터 정리한 파일을 적어보겠다. 

-- 2021-02-15 집합함수 (Group By)
/*
    전체 데이터를 대상으로 통계를 구하는 프로그램 
    COUNT() : 전체 로우의 갯수(등록한)
              = 로그인 처리 
              = 아이디 중복체크 
              형식) 
                   COUNT(*) : NULL값을 포함 
                   COUNT(column): NULL값을 제외 
    MAX() : 전체 데이터중에 최고값을 가지고 올때
              = 자동증가 번호  생성  => MAX()+1
                ===========  게시판 , 장바구니 , 예매하기 
    MIN() : 최소값 
    AVG() : 전체를 대상으로 평균  (column)
    SUM() : 전체를 대상으로 합 
    RANK() : 순위 결정 
             1 2 3 3 5
    DENSE_RANK() : 순위 결정 
             1 2 3 3 4
    CUBE() :   ROW단위 계산 + Column단위 계산
    ROLLUP() : ROW단위 계산 
    
    # 주의점 
    일반 컬럼과는 동시에 사용이 불가능하다 
    단일행 함수와 동시에 사용이 불가능하다 
    예)
        SELECT ename,count(*) FROM emp => (X)
        SELECT count(*),substr() FROM emp => (X)
*/
-- COUNT() 함수 => 등록된 갯수
-- 사원이 몇명인지 확인 
SELECT COUNT(*) FROM emp; -- NULL값을 포함 
SELECT COUNT(comm) FROM emp; -- NULL값을 제외 
SELECT COUNT(mgr) FROM emp;
-- 영화의 총갯수 = movie
SELECT COUNT(*) FROM movie;
-- 음악의 총갯수 = genie_music
SELECT COUNT(*) FROM genie_music;
/*
CREATE TABLE member(
   id VARCHAR2(10),
   pwd VARCHAR2(10)
);
INSERT INTO member VALUES('hong','1234');
INSERT INTO member VALUES('shim','1234');
COMMIT;
SELECT * FROM member;
*/
-- SELECT id FROM member WHERE id='kim';
-- 급여가 1500이상이고 3000이하인 사원의 갯수
-- sal>=1500 AND sal<=3000
-- sal BETWEEN 1500 AND 3000
SELECT COUNT(*) FROM emp
WHERE sal BETWEEN 1500 AND 3000;

SELECT COUNT(*) FROM emp
WHERE sal>=1500 AND sal<=3000;

-- 영화(Movie)에서  장르가 액션이 영화의 갯수를 확인 
SELECT COUNT(*) FROM movie
WHERE genre LIKE '%액션%';

SELECT COUNT(*) FROM movie
WHERE REGEXP_LIKE(genre,'액션');
-- 웹사이트 => 검색

-- 음악(genie_music) 가수중에 방탄소년단의 노래가 몇개 
SELECT singer FROM genie_music;
SELECT COUNT(*) FROM genie_music
WHERE singer='방탄소년단';
-- MAX => 최대값  => 형식 : MAX(column명) 
SELECT MAX(sal),MIN(sal) FROM emp;
SELECT MAX(empno),MIN(empno) FROM emp;

-- AVG(평균) => 형식) AVG(column명)
-- emp(저장공간)에 등록된 사원의 급여의 평균을 가지고 온다 
SELECT AVG(sal) FROM emp;
-- 사원중에 평균보다 급여가 많은 사원이 몇명인가?
SELECT COUNT(*) FROM emp
WHERE sal>2073;
SELECT COUNT(*) FROM emp
WHERE sal>(SELECT AVG(sal) FROM emp);
-- 서브쿼리
-- SUM(합)   => 형식) SUM(column명)
SELECT SUM(sal),ROUND(AVG(sal),0) FROM emp; 
-- 사원중에 사번이 홀수인 사원의 급여합 , 인원수 , 급여평균을 출력
SELECT SUM(sal),COUNT(*),AVG(sal) FROM emp
WHERE MOD(empno,2)=1;

-- deptno(부서번호) 부서별로 인원수,급여합,급여평균
-- 10 , 20 , 30
SELECT COUNT(*),SUM(sal),AVG(sal) FROM emp
WHERE deptno=10;
SELECT COUNT(*),SUM(sal),AVG(sal) FROM emp
WHERE deptno=20;
SELECT COUNT(*),SUM(sal),AVG(sal) FROM emp
WHERE deptno=30;
/*
SELECT deptno,COUNT(*),SUM(sal),AVG(sal) FROM emp
GROUP BY deptno;
*/
-- 누가 잘 묶는가? (메소드,클래스) => 함수
-- RANK => 형식) RANK() OVER(ORDER BY column명 ASC|DESC)
SELECT empno,ename,sal,RANK() OVER(ORDER BY sal DESC) "rank"
FROM emp;
SELECT empno,ename,sal,DENSE_RANK() OVER(ORDER BY sal DESC) "rank"
FROM emp;

-- 사원중에 입사한 순서로 등수를 설정 (이름,입사일, 등수)
SELECT ename,hiredate,RANK() OVER(ORDER BY hiredate ASC) "입사순"
FROM emp;
SELECT ename,hiredate,DENSE_RANK() OVER(ORDER BY hiredate ASC) "입사순"
FROM emp;
-- SORT
-- 사원의 이름을 A.B.C..
SELECT ename , RANK() OVER(ORDER BY ename ASC) "이름순"
FROM emp;

-- GROUP BY 
SELECT * FROM emp;
SELECT * FROM emp 
ORDER BY deptno ASC;

-- GROUP BY 컬럼명 (함수)
/*
     1.그룹함수는 사용이 가능 , 그룹으로 설정된 컬럼이나 함수를 제외하고 
       나머지는 같이 사용이 불가능
     
     SELECT deptno,ename,AVG(sal)
     FROM emp
     GROUP BY deptno;
     
     2. 그룹컬럼에 별칭을 사용 할 수 없다 
     
     
*/
-- 부서별 인원수 , 급여의 합
SELECT deptno,COUNT(*),SUM(sal)
FROM emp
GROUP BY deptno;

-- 입사년도별로 인원수 , 급여의 평균 (반올림)
-- 입사년도 1980 
SELECT TO_CHAR(hiredate,'YYYY'), COUNT(*), ROUND(AVG(sal),0)
FROM emp
GROUP BY hiredate;

SELECT TO_CHAR(hiredate,'RRRR'),COUNT(*),ROUND(AVG(sal),0)
FROM emp
GROUP BY TO_CHAR(hiredate,'RRRR')
ORDER BY TO_CHAR(hiredate,'RRRR');

-- 입사년도별로 인원수 , 급여 평균을 출력 => 전체 급여평균보다 많은 그룹 출력)
SELECT TO_CHAR(hiredate,'RRRR'),COUNT(*),ROUND(AVG(sal),0)
FROM emp
--WHERE sal>(SELECT AVG(sal) FROM emp)
-- WHERE sal>AVG(sal)
GROUP BY TO_CHAR(hiredate,'RRRR')
HAVING AVG(sal)>2073;

SELECT TO_CHAR(hiredate, 'YYYY'),COUNT(*), ROUND(AVG(sal),0)
FROM emp
WHERE sal > (SELECT AVG(sal) FROM emp)
GROUP BY  TO_CHAR(hiredate, 'YYYY')
ORDER BY  TO_CHAR(hiredate, 'YYYY');

-- 영화(movie) 개봉년도별로 영화 갯수가 몇개인지?
SELECT SUBSTR(regdate,1,4),COUNT(*) 
FROM movie
GROUP BY SUBSTR(regdate,1,4)
ORDER BY 1;
-- 뮤직(genie_music) 가수별 노래가 몇곡인지?
SELECT singer , COUNT(*)
FROM genie_music
GROUP BY singer;
/*
    SELECT문장의 순서
    ================
    SELECT 
    FROM 
    ================ 필수 
    [
       WHERE 
       ===========
       GROUP BY
       HAVING =======> 그룹에 대한 조건 GROUP BY가 있는 경우에만 사용이 가능
       ===========
       ORDER BY
    ]
*/
-- 이중 GROUP BY   ==> 컬럼명,컬럼명
SELECT * FROM emp
ORDER BY deptno;

SELECT deptno,job,COUNT(*),SUM(sal),AVG(sal)
FROM emp
GROUP BY deptno,job
ORDER BY deptno;

-- 부서별 => 부서안에 입사년도별 , SUM(sal) , COUNT(*)
SELECT deptno,TO_CHAR(hiredate,'YYYY'),SUM(sal),COUNT(sal)
FROM emp
GROUP BY deptno,TO_CHAR(hiredate,'YYYY')
ORDER BY deptno;

-- ROLLUP.CUBE => 반드시 GROUP BY를 이용한다 
SELECT deptno,job,COUNT(*)
FROM emp
GROUP BY ROLLUP(deptno,job);

SELECT NVL(deptno,0),NVL(job,'total'),COUNT(*)
FROM emp
GROUP BY CUBE(deptno,job);
-- 자바,오라클 => NULL값 
-- ROLLUP => 뮤직 => 가수명 , 상태 , COUNT(*)
SELECT singer,state , COUNT(*)
FROM genie_music
GROUP BY ROLLUP(singer,state);

SELECT singer,state , COUNT(*)
FROM genie_music
GROUP BY CUBE(singer,state);
/*
     1. GROUP BY (컴럼 , 함수(날짜 => DATE (TO_CHAR) , VARCHAR2 (SUBSTR))
     2. 그룹에 대한 조건 => HAVING 
     3. 그룹 함수 
        = COUNT(*) 
        = MAX()
        = AVG(),SUM()
        = RANK() , DENSE_RANK()
     4. ROLLUP , CUBE
     
     ==================== 기본 SQL
     ==================== 고급 SQL (JOIN,SUBQUERY) 
     = DDL 
     = TCL 
     = VIEW , SEQUENCE , INDEX , PL/SQL 
     = 오라클을 배우는 것이 아니라 => 자바에서 사용하는 오라클 SQL (2주) 
*/

집합함수의 경우에는 자바 문법에서 배운 메소드들과 크게 다르지 않아서 자주 사용하는 것들만 외워두면 금세 익힐 것 같다. 특히 MAX(), COUNT(), SUM()과 같은 함수들이 자주 사용된다고 하니 이 부분을 집중적으로 공부하면 되지 않을까 싶다. 

 

GROUP BY는 표시할 내용들을 그룹으로 묶어서 보여줄때 사용하는 함수이다. 

이때 오름차순이나 내림차순으로 그룹을 표시하고 싶으면 ORDER BY를 사용해서 정리해주면 된다. 

 

/*
    page 18 => DBMS (면접) 
    page 19 => SQL 
      SQL 
       DML (SELECT,INSERT,UPDATE,DELETE)
       DDL (CREATE , ALTER , DROP , RENAME, TRUNCATE)
       TCL (COMMIT, ROLLBACK)
    page 26 => SELECT 문법
               ======= 출력 , 컬럼 대신 , 테이블 대신 
                            ==========  ==========
                             스칼라 서브쿼리 , 인라인 뷰 
       SELECT * | column1,column2...
             ===  ==================
             page 26    page 29
       FROM table명|View명|SELECT ~~
       [
          WHERE
          GROUP BY
          HAVING
          ORDER BY
       ]
       
    page 33 => 별칭 => 함수로 출력 , 컬럼명이 길다 
       = 컬럼명 "별칭"
       = 컬럼명 as 별칭 
    page 34 => 중복을 제거 : DISTINCT (컬럼 앞에 사용)
       SELECT DISTINCT deptno ~~
    page 37 => 문자열 결합 : ||
               =====
               '' => 문자,문자열,날짜 (숫자 => ''을 붙여도 상관이 없다 (자동형변환)=> 속도가 늦다)
               
    page 36 => ORDER BY 
            1. 정렬 (오라클은 빈공간에 데이터를 저장하기 때문에 순서가 존재하지 않는다) 
            2. ORDER BY 컬럼번호,컬럼명,함수 ASC|DESC => ASC는 생략이 가능 
                        =======
               SELECT * FROM emp
               ORDER BY 1 => empno
            3. 이중 정렬 =>() ,() => 댓글 , 답변형 게시판 
                         ===  ==
    page 40 => WHERE (조건문) 
               ====== 연산자 
               산술 연산자 : 주로 SELECT뒤에 
               나머지 연산자 : boolean => WHERE 문장 뒤에 
               ===========
                비교연산자 : = , !=(<>) , < , > , <= ,>=
                논리연산자 : AND , OR
                대입연산자 : = (UPDATE)
                NOT,NULL,BETWEEN,IN(OR가 여러개),LIKE(%,_)
                === ===== 연산처리가 안된다 => IS NULL , IS NOT NULL 
                NOT IN()
                NOT BETWEEN
                NOT LIKE 
                NOT (sal>= AND sal<=)
    page 41 => 문자 조회는 '' , 대소문자 구분  (page 43)
    page 45 => 연산자 종류 (45~56)
    page 56 => ORDER BY 
    page 59 => 집합 연산자(테이블 2개에서 데이터를 얻어오기)
               UNION :  데이터 전체를 가지고 온다 (단 중복은 제거)
                  A : 12345 
                  B : 34567    ==> 1234567
               UNION ALL : 데이터 전체를 가지고 온다 (FULL OUTER JOIN)
                  A : 12345 
                  B : 34567    ==> 1234534567
               INTERSECT : 교집합  (INNER JOIN)
                  A : 12345 
                  B : 34567    ==> 345
               MINUS : 같은 데이터 제외하고 나머지 
                  A : 12345 
                  B : 34567    ==> A-B :12 , B-A : 67
               INTERSECT+(A-B) : LEFT OUTER JOIN
               INSERSECT+(B-A) : RIGHT OUTER JOIN
               
    page 68 : 단일행 , 집합함수 
    page 69 : 단일행 
              =====
              문자함수 , 숫자함수 , 날짜함수 ,변환함수 ,일반함수 
    page 70 : 문자함수 
              SUBSTR() : 75 page
              LENGTH() : 73 page
              INSTR()  : 76 page
              RPAD ()  : 81 page
              REGEXP_LIKE() : 124 page
    page 86 : 숫자함수 
              ROUND() : 반올림 => 86 page
              TRUNC() : 버림   => 86 page
              MOD() : 나머지   => 87 page
              CEIL(): 올림    => 87 page
    page 89 : 날짜함수 
              SYSDATE : 시스템의 날짜 , 시간 => 90 page
              MONTHS_BETWEEN()            => 91 page
    page 99 : 형변환함수 
              TO_CHAR () :문자열 변환 (page 102(년도,월,일,시간,분,초)
                                     (page 107 (숫자변환))
              page 99 => 오라클에서 사용하는 데이터형 
              문자형 (CHAR , VARCHAR2,CLOB) => String
              숫자형 (NUMBER) => int ,double
              날짜형 (DATE,TIMESTAMP) => java.util.Date
    page 110 : 일반함수
               NVL() : NULL값일 경우에 대체하는 함수 : 110page
               DECODE() : 다중 조건문 : 113page
    집합함수 
    page 158 => COUNT(159),SUM(159),AVG(160),MAX(160),RANK(198) , CUBE(176),ROLLUP(167)
                ===============================================
    page 162 => GROUP BY (162~166)
*/
-- SELECT * FROM genie_music;
/*
SELECT * FROM emp;
SELECT ename,empno,hiredate
FROM emp
ORDER BY 1;
*/

 

오라클에서 중요한 함수들과 책 페이지를 같이 적어주신 필기이다. 여기 나온 함수들을 위주로 공부하면 되지 않을까 싶다. 

 

-- 2021-02-15(4장 - 조인 : SQL고급과정)
/*
     2개이상의 테이블로부터 데이터 수집 경우 : 조인(JOIN)
                        ======
     2개이상의 SQL문장을 합쳐서 데이터 수집 : 서브쿼리    ===> SELECT 
            ================
            
     조인 
      1) 테이블 한개이상에서 필요한 데이터를 찾아오기 
         ============
      2) 조인의 종류 
         = INNER JOIN => 교집합 (값이 같은 것이 있는 경우)
           = EQUI_JOIN
             1. Oracle JOIN
             2. ANSI JOIN
             3. NATURAL JOIN
             4. JOIN~USING
           = NON_EQUI_JOIN
             1. Oracle JOIN
             2. ANSI JOIN
         = OUTER JOIN
           = LEFT OUTER JOIN
           = RIGHT OUTER JOIN
           = FULL OUTER JOIN
*/
SELECT * FROM emp;
SELECT * FROM dept;
/*
SELECT * FROM salgrade;
CREATE TABLE salgrade(
    grade NUMBER,
    losal NUMBER,
    hisal NUMBER
);
INSERT INTO salgrade VALUES(1,700,1200);
INSERT INTO salgrade VALUES(2,1201,1400);
INSERT INTO salgrade VALUES(3,1401,2000);
INSERT INTO salgrade VALUES(4,2001,3000);
INSERT INTO salgrade VALUES(5,3001,9000);
COMMIT;
*/
/*
     INNER JOIN 
     1) EQUI_JOIN
        = Oracle JOIN (A,B) (오라클에서만 사용이 가능)
          SELECT A.col1,A.col2,B.col1,B.col2
          FROM A,B
          WHERE A.col3=B.col3;
        = ANSI JOIN(표준화=>모든 데이터베이스 공동으로 사용이 가능)
          SELECT A.col1,A.col2,B.col1,B.col2
          FROM A (INNER) JOIN B
          ON A.col3=B.col3;
*/
-- emp (사번 , 이름 ,직위, 입사일) , dept (부서명,근무지)  => deptno
SELECT empno,ename,job,hiredate,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno;
-- 테이블의 별칭을 사용 (테이블명이 글자수의 제한)
SELECT empno,ename,job,hiredate,dname,loc
FROM emp e,dept d
WHERE e.deptno=d.deptno;

-- ANSI 
SELECT empno,ename,job,hiredate,dname,loc
FROM emp INNER JOIN dept
ON emp.deptno=dept.deptno;

SELECT empno,ename,job,hiredate,dname,loc
FROM emp JOIN dept
ON emp.deptno=dept.deptno;
------------------------------------- 테이블이 같은 컬럼명이 존재해야 한다 (다른 컬럼을 비교해서 사용:값이 동일)
-- 자연조인
SELECT empno,ename,job,hiredate,dname,loc
FROM emp NATURAL JOIN dept;

-- JOIN _ USING
SELECT empno,ename,job,hiredate,dname,loc
FROM emp JOIN dept USING(deptno);
--------------------------------------------
/*
     테이블 => 컬럼명이 다른 경우에는 컬럼명만 사용해도 된다 , 같은 컬럼명이면 어느 테이블에서 가지고 올 것인지 설정 
*/
SELECT empno,ename,job,hiredate,dname,loc,e.deptno
FROM emp e,dept d
WHERE e.deptno=d.deptno;
/*
     NON EQUI_JOIN : JOIN~USING,NATURAL JOIN은 사용 할 수 없다 
     ============== =이 아닌 다른 연산자를 사용할 경우에 (BETWEEN, >= AND <=)
     EQUI_JOIN : (연산자 = ) => 단점 (연산자를 사용 했기 때문에 NULL값이 있는 경우에는 처리가 불가능하다)
*/
SELECT ename,sal,hiredate,grade
FROM emp,salgrade 
WHERE sal BETWEEN losal AND hisal;
/*
      emp(사원정보)
        empno : 사번
        ename : 이름
        job : 직위
        mgr : 사수번호
        hiredate : 입사일
        sal : 급여
        comm : 성과급
        deptno : 부서번호 
      dept(부서정보)
        deptno : 부서번호
        dname : 부서명
        loc : 근무지 
      salgrade(급여등급)
        grade : 등급 (호봉)
        losal : 최저급여
        hisal : 최대급여 
*/
-- 조인 조건 , 개인 조건 
-- 이름,직위,입사일,급여,부서명,근무지 출력 => 사번이 7788인 사원의 정보출력 
SELECT ename,job,hiredate,sal,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno
AND empno=7788;

-- 위에 Oracle JOIN => ANSI JOIN으로 변경 
SELECT ename,job,hiredate,sal,dname,loc
FROM emp JOIN dept
ON emp.deptno=dept.deptno
AND empno=7788;

-- emp(ename,job,hiredate,sal) , dept(dname,loc) , salgrade(grade)
-- 1. Oracle JOIN
SELECT ename,job,hiredate,sal,dname,loc,grade
FROM emp,dept,salgrade
WHERE emp.deptno=dept.deptno
AND sal BETWEEN losal AND hisal;
-- 2. ANSI JOIN
SELECT ename,job,hiredate,sal,dname,loc,grade
FROM emp 
JOIN dept
ON emp.deptno=dept.deptno
JOIN salgrade
ON sal BETWEEN losal AND hisal;

-- 한개의 테이블에서 조인이 가능 => 반드시 테이블에 별칭을 사용한다 
-- emp(본인 이름),emp(사수 이름)
/*
    조인 조건 
    1. 컬럼명이 같다 (같은 값을 가지고 있다)
       ===========
       primary key , foreign key
    2. 컬럼명이 다르다 (같은 값을 가지고 있다) => 게시판 <==> 댓글 
*/
-- self join
SELECT e1.ename "본인 이름",e2.ename "사수 이름"
FROM emp e1,emp e2
WHERE e1.mgr=e2.empno;
-- 조건검색에 컬럼명이 다르면 NATURAL JOIN,JOIN~USING은 사용이 불가능하다 

-- emp (사번 , 이름 , 직위 , 성과급 , 급여) , dept(부서명 , 근무지) => JOIN , 성괴급을 받는 사원에 대해서만 출력 
SELECT empno,ename,job,comm,sal,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno
AND comm IS NOT NULL AND comm<>0;

-- ANSI JOIN
SELECT empno,ename,job,comm,sal,dname,loc
FROM emp JOIN dept
ON emp.deptno=dept.deptno
AND comm IS NOT NULL AND comm<>0;

-- emp (사번 , 이름 ,직위 , 성과급, 급여) , dept(부서명,근무지 )=> JOIN , 이름중에 A를 포함하고 있는 사원의 정보를 출력 
-- Oracle Join
SELECT empno,ename,job,comm,sal,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno
AND ename LIKE '%A%';
-- ANSI JOIN
SELECT empno,ename,job,comm,sal,dname,loc
FROM emp JOIN dept
ON emp.deptno=dept.deptno
AND ename LIKE '%A%';

-- emp (사번 , 이름 ,직위 , 성과급, 급여) , dept(부서명,근무지 )=> JOIN , 81년에 입사한 사원에 대해서 출력 
SELECT empno,ename,job,comm,sal,hiredate,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno
AND SUBSTR(hiredate,1,2)=81;

SELECT empno,ename,job,comm,sal,hiredate,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno
AND hiredate LIKE '81%';

SELECT empno,ename,job,comm,sal,hiredate,dname,loc
FROM emp JOIN dept
ON emp.deptno=dept.deptno
AND hiredate LIKE '81%';
/*
    자바 : 포함 클래스 
                   사용자 요청               SQL 
    브라우저(HTML)  <========> 자바(파이썬) <=========> 오라클
                     전송                  실행 결과
       
*/
-- OUTER JOIN (INNER JOIN + 알파) => null값을 포함해서 데이터를 가지고 온다 
/*
      = LEFT OUTER JOIN
        1. Oracle JOIN (A,B => col1,col2,col3(공통된 데이터가 있다))
        A.col3  B.col3
          1       1
          2       2
          3       3
          4  (출력을 할 수 없다)
           SELECT A.col1,A.col2,B.col1,B.col2
           FROM A,B
           WHERE A.col3=B.col3(+)
        2. ANSI JOIN 
           SELECT A.col1,A.col2,B.col1,B.col2
           FROM A LEFT OUTER JOIN B
                  ===============
           ON A.col3=B.col3
      = RIGHT OUTER JOIN
        1. Oracle JOIN
           SELECT A.col1,A.col2,B.col1,B.col2
           FROM A,B
           WHERE A.col3(+)=B.col3
        2. ANSI JOIN 
           SELECT A.col1,A.col2,B.col1,B.col2
           FROM A RIGHT OUTER JOIN B
                  ===============
           ON A.col3=B.col3
      = FULL OUTER JOIN(사용빈도가 별로 없다)
        1. ANSI JOIN
           SELECT A.col1,A.col2,B.col1,B.col2
           FROM A FULL OUTER JOIN B
                  ===============
           ON A.col3=B.col3
*/
-- RIGHT 
SELECT empno,ename,job,dept.deptno,dname,loc
FROM emp,dept
WHERE emp.deptno(+)=dept.deptno;

SELECT empno,ename,job,dept.deptno,dname,loc
FROM emp RIGHT OUTER JOIN dept
ON emp.deptno=dept.deptno;

SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1, emp e2
WHERE e1.mgr=e2.empno(+);

SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1 LEFT OUTER JOIN emp e2
ON e1.mgr=e2.empno;

SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1 FULL OUTER JOIN emp e2
ON e1.mgr=e2.empno;
-- 14 (KING,BLAKE,JONES , FORD, SCOTT , CLARK)

 JOIN부터는 조금 헷갈리기 시작했다. 특히 INNER JOIN은 그냥저냥 잘 이해한거 같은데 OUTER JOIN이 나온 순간부터 또 헷갈리기 시작했다. 내가 왼쪽 오른쪽을 안그래도 잘 구분을 못해가지고... 

 

일단 정리를 해보면 같은 COLUMN명이 있는 테이블들을 조합할때는 EQUI_JOIN을 사용한다. 

대표적인 예시는 아래와 같다. 

 

SELECT empno,ename,job,hiredate,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno;

 deptno column이 같기 때문에 위와 같이 적어줄 수 있었다. 위는 oracle join 방식이고

ANSI JOIN은 아래와 같이 써주면 된다. 

 

SELECT empno,ename,job,hiredate,dname,loc
FROM emp INNER JOIN dept
ON emp.deptno=dept.deptno;

크게 다른 점은 없고, 그냥 INNER JOIN을 써주고 WHERE 대신 ON을 써준다는 점을 잘 기억하면 된다. 

 

 

NON EQUI_JOIN은 = 을 쓰지 않는 JOIN 방식이다. 

대표적인 예로 아래 코드를 들 수 있다. 

SELECT ename,sal,hiredate,grade
FROM emp,salgrade 
WHERE sal BETWEEN losal AND hisal;

 emp와 salgrade는 같은 column을 공유하지 않는다. 그렇기 때문에 between and와 같은 연산기호를 사용해서 값을 가져올수 있도록 하고 있다. 

 

한개의 테이블에서 JOIN이 가능한 경우도 있다. 이 경우를 SELF_JOIN 이라고 한다. 대신 꼭 테이블 별칭을 사용해서 값들을 구분해서 가져와야한다. 

SELECT e1.ename "본인 이름",e2.ename "사수 이름"
FROM emp e1,emp e2
WHERE e1.mgr=e2.empno;

이런식으로 사용이 가능하다. mgr은 사수의 사번이기 때문에 WHERE 조건절을 저렇게 걸어주었다. 

 

나를 헷갈리게 만들었던 OUTER_JOIN

-- RIGHT 
SELECT empno,ename,job,dept.deptno,dname,loc
FROM emp,dept
WHERE emp.deptno(+)=dept.deptno;

SELECT empno,ename,job,dept.deptno,dname,loc
FROM emp RIGHT OUTER JOIN dept
ON emp.deptno=dept.deptno;

SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1, emp e2
WHERE e1.mgr=e2.empno(+);

SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1 LEFT OUTER JOIN emp e2
ON e1.mgr=e2.empno;

SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1 FULL OUTER JOIN emp e2
ON e1.mgr=e2.empno;
-- 14 (KING,BLAKE,JONES , FORD, SCOTT , CLARK)

그러니까 나중에 볼 내가 이해하기 쉽게 정리를 해보자면

왼쪽에 정보가 더 많아서 오른쪽의 테이블이 따라 붙어야 하는 경우를 LEFT_JOIN,

오른쪽에 정보가 더 많아서 왼쪽의 테이블이 따라 붙어야 하는 경우를 RIGHT_JOIN이라고 해준다. 

 

그리고 내용이 더 적어서 따라 붙어야 하는 쪽에 (+)를 표기해주면 된다. 

이렇게 정리해서 이해하니 생각보다 엄청 복잡한 개념은 아니었다. 

 

 

 

728x90
반응형

'programming > Gukbi' 카테고리의 다른 글

국비 교육 37일차 - DML, 제약조건  (0) 2021.02.17
국비 교육 36일차 - JOIN, JAVA-ORACLE 연동  (0) 2021.02.16
국비 교육 34일차 - ORACLE  (0) 2021.02.10
국비 교육 33일차 - DB  (0) 2021.02.09
국비 교육 32일차 - DB  (0) 2021.02.08