본문 바로가기
DB

[DB / Oracle] Chapter 6. 두 개 이상의 테이블에서 SQL 질의(JOIN, 부속질의)

by nyeoo 2023. 11. 28.

1. JOIN(조인)

  • 두 테이블에 중복된 컬럼이 아니더라도 컬럼의 소속 테이블을 명시해 주는 것을 권장함
  • 왜냐하면, 오라클 입장에서는 먼저 EMP 테이블에 들러서 컬럼이 있는것을 확인하더라도 다른 테이블인 DEPT 테이블에 들러서 또 한 번 해당 컬럼이 있는지를 확인하기 때문임
  • DEPT 테이블에는 DEPTNO 데이터가 하나 씩만 들어가 있고 EMP 테이블에는 여러개 들어가 있으므로 DEPT가 부모 테이블. 따라서, 부모 테이블인 DEPT 테이블의 컬럼을 참조할 수 있도록 처리할 것

▶ SQL 1992 CODE

▷ CROSS JOIN

  • 수학에서 말하는 데카르트 곱(CATERSIAN PRODUCT). 즉, 두 테이블을 결합한 모든 경우의 수 (14 * 4 = 56)
  • 많이 사용되지는 않음
  • 사용 예 
  • SELECT * FROM EMP, DEPT;

▷ EQUI JOIN

  • 서로 정확히 일치하는 데이터들끼리 연결하여 결합시키는 결합 방법. 결합시킬 때 조건이 필요하므로 조건절 사용
  • 두 테이블간의 관계를 명확하게 파악하고 있어야 사용가능
  • 사용 예
    SELECT *
    FROM EMP E, DEPT D
    WHERE E.DEPTNO = D.DEPTNO;

▷ NON EQUI JOIN

  • 범위 안에 적합한 데이터들끼리 연결시키는 결합 방식
  • 사용 예
    SELECT *
    FROM EMP E, SALGRADE S
    WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL;

▷ EQUI JOIN 시 (+) 를 활용한 결합 방법

  • (+)가 없는 쪽 테이블(기준)의 데이터를 모두 메모리에 적재한 후, (+)가 있는 쪽 테이블(첨가)의 데이터를 하나하나 확인하여 결합시키는 형태로 JOIN 이 이루어짐
  • 사용 예
    SELECT *
    FROM TBL_EMP E, TBL_DEPT D
    WHERE E.DEPTNO = D.DEPTNO(+);

▶ SQL 1999 CODE

  • 『JOIN』 키워드 등장 : JOIN(결합)의 유형을 명시하는 방식으로 표준화됨
  • 『ON』 키워드 등장 : 결합조건은 WHERE 대신 ON 사용

▷ CROSS JOIN

  • 1992 CODE CROSS JOIN과 같은 기능. CROSS JOIN 키워드 사용
  • 사용 예
    SELECT *
    FROM EMP CROSS JOIN DEPT;

▷ INNER JOIN

  • 1992 CODE EQUI JOIN과 같은 기능
  • INNER JOIN 키워드 에서 INNER는 생략가능함
  • 사용 예
    SELECT *
    FROM EMP E INNER JOIN DEPT D ON E.DEPTNO = D.DEPTNO;
    SELECT *
    FROM EMP E JOIN DEPT D ON E.DEPTNO = D.DEPTNO;

▷ OUTER JOIN

  • 1992 CODE에서 EQUI JOIN에 (+)를 활용하는 방식과 같은 기능이지만, 다른 점은 RIGHT, LEFT, FULL 키워드를 사용한다는 것
  • 유의할 점은, EQUI JOIN에서는 (+)가 안 붙은 테이블이 기준이었는데 OUTER JOIN은 LEFT, RIGHT 키워드로 가리키는 테이블이 기준이 됨
  • OUTER JOIN 키워드 에서 OUTER는 생략가능함
  • 사용 예
    SELECT *
    FROM TBL_EMP E OUTER LEFT JOIN TBL_DEPT D
    ON E.DEPTNO = D.DEPTNO;
    SELECT *
    FROM TBL_EMP E LEFT JOIN TBL_DEPT D
    ON E.DEPTNO = D.DEPTNO;

▶ SELF JOIN (자기조인)

  • 자신의 테이블을 대상으로 JOIN 하는 것
  • 사용 예
    SELECT P.EMPNO 사원번호, P.ENAME 사원명, P.JOB 직종명, P.MGR 관리자번호, E.ENAME 관리자명, E.JOB 관리자직종명
    FROM EMP P LEFT JOIN EMP E
    ON E.EMPNO = P.MGR;

▶ NATURAL JOIN

  • 두 테이블의 동일한 이름을 가지는 칼럼이 모두 JOIN됨
  • 두 테이블간의 관계를 확인하는 용도로 이러한 JOIN 방식을 사용하는 것이 아닌, 프로그램을 구성하는 용도로 NATURAL JOIN(오라클에게 맡기는 방식)은 바람직하지 않음
  • 사용 예
    SELECT DEPTNO, DNAME, ENAME, SAL
    FROM EMP E NATURAL JOIN DEPT D;

▶ 세 개 이상의 테이블 조인(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
        JOIN 테이블명3
        ON 테이블명2.컬럼명2 = 테이블명3.컬럼명2;

▶ ON과 WHERE

--①
SELECT *
FROM TBL_EMP E JOIN TBL_DEPT D
ON E.DEPTNO = D.DEPTNO
AND E.JOB = 'CLERK';
--②
SELECT *
FROM TBL_EMP E JOIN TBL_DEPT D
ON E.DEPTNO = D.DEPTNO
WHERE E.JOB = 'CLERK';

→ ①과 같은 방식으로 쿼리문을 구성하여도 조회 결과를 얻는 과정에는 문제가 없지만, ON 은 결합에 관한 조건을 명시할 때 사용하는 것이고, CLERK은 선택에 관한 조건이므로 ②방식이 바람직함

▶ USING

  • 두 개의 테이블을 INNER JOIN할 때, 두 테이블의 컬럼명이 같을 경우 JOIN 조건을 간단하게 적을 수 있도록 함
  • 사용 예
    SELECT DEPTNO, DNAME, ENAME, SAL
    FROM EMP E JOIN DEPT D
    USING(DEPTNO);

2. 부속질의(서브쿼리)

  • 서브쿼리(Sub Query)는 한 문장의 SQL 안에 또 다른 SQL이 부가적으로 사용한 것
  • 서브쿼리는 SELECT, FROM, WHERE, HAVING, ORDER BY, INSERT문의 VALUES, UPDATE문의 SET에 사용 가능
  • 사용되는 위치에 따라 FROM 절에 사용시 인라인 뷰, SELECT 절에 사용시 스칼라 서브쿼리, WHERE 절에 사용시 서브쿼리 라고 불림

▶ 단독 서브 쿼리, 상관 서브 쿼리

구분 설명
단독 서브 쿼리 메인 SQL의 테이블과 상관없이 단독으로 실행이 가능한 서브 쿼리문
상관 서브 쿼리(서브 상관 쿼리) 메인 쿼리에 있는 테이블의 컬럼이 서브 쿼리의 조건절(WHERE절, HAVING절)에 사용되는 서브 쿼리문

 

  • 상관 서브 쿼리 사용 예
    SELECT E.ENAME "사원명", E.SAL "급여", (SELECT COUNT(*) + 1
                                          FROM EMP
                                          WHERE SAL > E.SAL) "급여등수"
    FROM EMP E;

▶서브쿼리 연산자

종류 연산자 설명
비교 =, >, <, ≥, ≤, <> 서브쿼리가 단일행, 단일 열을 반환해야 처리가능함
집합 IN, NOT IN 서브쿼리가 다중행, 다중열을 반환가능하며, 속성값과 서브쿼리 결과 집합을 비교하여 하나라도 있으면 참. NOT IN 은 반대로 값이 존재하지 않으면 참
한정 ALL, ANY 비교 연산자와 함께 사용되며, ALL은 『모든』, ANY는 『최소 하나라도』 를 의미함
존재 EXISTS, NOT EXISTS 메인 쿼리에서 제공된 속성값이 서브쿼리의 조건을 만족하여 값이 존재하는지 확인. NOT EXISTS는 반대로 동작함