기본 콘텐츠로 건너뛰기

180921 JOIN, SUB QUERY

JOIN, SUB QUERY



1. 서브쿼리
 1) 서브쿼리 사용 가능한 장소
 - SELECT 절
 - FROM 절
 - WHERE 절
 - HAVING 절
 - ORDER BY 절
 - INSERT VALUES 절
 - UPDATE SET 절

 2) 유형
 - 단일행: SELECT문에서 하나의 행만 찾기
 - 한 행에 대한 결과값만 반환
 - 등호, 부등호 이용 (=, <, > ...)

 예) SELECT ename  이름, dno 사번
       FROM emp
       WHERE dno = (SELECT dno FROM emp WHERE eno = 20);
  => 20번 사원과 같은 부서에서 일하는 사원 찾기


 - 다중행: SELECT 문에서 하나 이상의 행 찾기
 - 여러 행에 대한 값 반환
 - 다중행 서브쿼리때 단일행 서브쿼리에서 사용하는 등호나 부등호 사용시 에러
 - IN, NOT IN, ALL, ANY, EXISTS

  -- IN: 서브쿼리 결과에 존재하는 임의의 값과 동일한 조건
  -- ALL: 서브쿼리에 존재하는 모든 값을 만족하는 조건 의미
  -- ANY: 서브쿼리 내에 존재하는 값 중 어느 하나라도 만족하면 출력
  -- EXISTS: 서브쿼리의 결과를 만족하는 값이 존재하는지 여부 판단, 조건을 만족하는 건이 1건을 찾으면 더이상 찾지 않음

 예) SELECT ename 이름, sal 급여
       FROM emp
       WHERE deptno != 20
                  AND sal > ANY(SELECT sal FROM emp WHERE job = 'SALESMAN');
  => SALESMAN 중 한 명보다 급여를 많이 받는 사원명과 급여

       SELECT ename 이름, sal 급여
       FROM emp
       WHERE deptno != 20
                   AND sal > ALL(SELECT sal FROM emp WHERE job='SALESMAN');
  => 모든 SALESMAN보다 급여를 많이 받는 사원명과 급여

 - 다중열(다중컬럼): SELECT 문장 하나 이상의 컬럼을 검색하는 질의
 - 서브쿼리에서 여러 열(컬럼)에 대한 결과 값을 반환
 - 서브쿼리와 메인쿼리에서 비교하고자 하는 컬럼 개수와 위치가 동일해야 함
 - 서브쿼리의 결과로 여러 개의 컬럼이 반환되어 메인쿼리와 동시에 비교되는 것

 예) SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, HEIGHT 키
       FROM PLAYER
       WHERE (TEAM_ID, HEIGHT) IN (SELECT TEAM_ID, MIN(HEIGHT)
                                                                 FROM PLAYER
                                                                 GROUP BY TEAM_ID)
       ORDER BY TEAM_ID, PLAYER_NAME;
  => 선수 테이블에서 키가 가장 작은 선수의 팀코드와 키를 잡아내서 팀코드와 선수이름으로 정렬

 - FROM절 상의 서브쿼리: inline view
 - VIEW처럼 작용

 예) SELECT e.ename, e.salary, a.avg_sal
       FROM employee e, (SELECT dno, AVG(salary) avg_sal 
                                        FROM employee GROUP BY dno) a
       WHERE e.dno = a.dno;
  => 사원 정보와 각 사원이 속한 부서의 평균 급여를 함께 출력


2. JOIN
 - 2개 이상의 테이블을 연결하여 데이터를 검색하는 법
 1-1) EQUI JOIN
 - 두 테이블 간 값이 일치하는 경우
 - JOIN 조건으로 '=' 연산자 이용

 예) SELECT e.eno 사번, e.ename 사원명, d.dno 부서번호, d.dname 부서명
       FROM employee e, department d
       WHERE e.dno = d.dno;
  => 사원이 어떤 부서에 근무하는지 출력


 1-2) NON EQUI JOIN
 - 두 테이블 간 값이 일치하지 않는 경우
 - 범위 연산자 사용 (BETWEEN ~ AND  ~)

 예) SELECT e.ename 사원명, e.salary 급여, s.grade 등급
       FROM employee e, salary s
       WHERE e.salary BETWEEN s.low_sal AND s.high_sal
  => 사원이 받는 급여 등급 조회


 2-1) inner JOIN
 - 교집합
 - 두 테이블 간의 조인 조건을 만족하는 row만 출력

 예) SELECT e.eno 사번, e.ename 사원명, d.dno 부서번호, d.dname 부서명
       FROM employee e INNER JOIN department d
       ON e.dno = d.dno;
  => 사원이 어떤 부서에 근무하는지 출력(EQUI JOIN과 동일한 결과)


 2-2) outer JOIN
 - JOIN 조건에서 한쪽 값이 없어도 row 반환(출력)
 - 동일 조건에서 조인 조건을 만족하는 값이 없는 행을 조회하기 위해 사용
 - (+) 연산자 사용
 - ANSI 표준인 LEFT / RIGHT / FULL JOIN도 사용 가능

  -- LEFR OUTER JOIN: JOIN 수행 시 왼쪽 테이블 데이터를 기준으로 JOIN 수행
  -- RIGHT OUTER JOIN: JOIN 수행 시 오른쪽 테이블 데이터를 기준으로 JOIN 수행
  -- FULL OUTER JOIN: JOIN 수행 시 왼, 오른 모든 테이블의 데이터를 읽어 JOIN 수행

 예) SELECT e.eno 사번, e.ename 사원명, d.dno 부서번호, d.dname 부서명
       FROM employee e LEFT OUTER JOIN department d
       ON e.dno = d.dno;
  => 사원이 어떤 부서에 근무하는지 검색, 부서를 아직 배정받지 못한 사원도 검색

 예) SELECT e.eno 사번, e.ename 사원명, d.dno 부서번호, d.dname 부서명
       FROM department d RIGHT OUTER JOIN employee e
       ON e.dno = d.dno;
  => 사원이 어떤 부서에 근무하는지 검색, 부서를 아직 배정받지 못한 사원 및 사원이 없는 부서도 검색