본문 바로가기

DB

Oracle 11g 조인 정리

 

1) 조인 기본 종류 요약

조인 종류 설명 예제 실무 활용
INNER JOIN 양쪽 테이블에서 조건 일치 행만 반환한다.
SELECT e.first_name, d.department_name
FROM employees e
JOIN departments d
  ON e.department_id = d.department_id;
정확한 관계가 있을 때 기본으로 사용한다.
LEFT OUTER JOIN 왼쪽 테이블은 모두, 오른쪽은 매칭될 때만 반환한다.
SELECT e.first_name, d.department_name
FROM employees e
LEFT JOIN departments d
  ON e.department_id = d.department_id;
누락 데이터가 있어도 왼쪽 기준으로 모두 조회한다.
RIGHT OUTER JOIN 오른쪽 테이블은 모두, 왼쪽은 매칭될 때만 반환한다.
SELECT e.first_name, d.department_name
FROM employees e
RIGHT JOIN departments d
  ON e.department_id = d.department_id;
마스터(오른쪽) 기준 전체 목록에 매핑 상태를 보고 싶을 때 쓴다.
FULL OUTER JOIN 양쪽 전체를 합쳐 보여주며, 매칭 안 되는 컬럼은 NULL이다.
SELECT e.first_name, d.department_name
FROM employees e
FULL OUTER JOIN departments d
  ON e.department_id = d.department_id;
양쪽 누락을 함께 파악한다.
NATURAL JOIN 동명이 컬럼으로 자동 조인한다. 조건을 직접 쓰지 않는다.
SELECT *
FROM employees NATURAL JOIN departments;
의도치 않은 컬럼이 엮일 수 있어 권장하지 않는다.
SELF JOIN 자기 자신과 조인한다.
SELECT e.first_name AS employee,
       m.first_name AS manager
FROM employees e
JOIN employees m
  ON e.manager_id = m.employee_id;
상하 관계, 부모-자식 구조 조회에 사용한다.
CROSS JOIN 곱집합을 반환한다.
SELECT *
FROM employees
CROSS JOIN departments;
테스트나 조합 생성에 드물게 사용한다.

2) 실무에서 자주 쓰는 기본 패턴

2-1. 직원과 부서 함께 조회 (INNER JOIN)

SELECT e.employee_id, e.first_name, d.department_name
FROM employees e
INNER JOIN departments d
  ON e.department_id = d.department_id;

2-2. 부서 미배정 직원도 포함 (LEFT JOIN)

SELECT e.employee_id, e.first_name, d.department_name
FROM employees e
LEFT JOIN departments d
  ON e.department_id = d.department_id;

2-3. 자기 자신과 조인 (SELF JOIN, 직원 ↔ 매니저)

SELECT e.employee_id,
       e.first_name  AS employee,
       m.first_name  AS manager
FROM employees e
JOIN employees m
  ON e.manager_id = m.employee_id;

3) 조인 + 집계/윈도우/서브쿼리 조합

3-1. 부서별 인원 수 (LEFT JOIN + GROUP BY + HAVING)

직원이 5명 이상인 부서만 조회한다.

SELECT d.department_name,
       COUNT(e.employee_id) AS emp_count
FROM departments d
LEFT JOIN employees e
  ON d.department_id = e.department_id
GROUP BY d.department_name
HAVING COUNT(e.employee_id) >= 5;

3-2. 부서별 급여 합을 행에 함께 표기 (PARTITION BY)

SELECT e.department_id,
       e.first_name,
       e.salary,
       SUM(e.salary) OVER (PARTITION BY e.department_id) AS dept_total
FROM employees e;

3-3. 부서별 급여 순위 (RANK + PARTITION BY)

SELECT e.first_name,
       e.department_id,
       e.salary,
       RANK() OVER (PARTITION BY e.department_id ORDER BY e.salary DESC) AS sal_rank
FROM employees e;

3-4. 부서별 연봉 상위 3명 (윈도우 순위 필터)

SELECT *
FROM (
  SELECT e.*,
         RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rnk
  FROM employees e
)
WHERE rnk <= 3;

3-5. WITH로 평균 급여 구해 조인 (WITH + JOIN + 조건)

WITH dept_avg AS (
  SELECT department_id, AVG(salary) AS avg_sal
  FROM employees
  GROUP BY department_id
)
SELECT e.first_name,
       e.salary,
       d.avg_sal
FROM employees e
JOIN dept_avg d
  ON e.department_id = d.department_id
WHERE e.salary >= d.avg_sal;

3-6. 3테이블 조인 (직원 + 부서 + 지역)

SELECT e.first_name,
       d.department_name,
       l.city
FROM employees  e
JOIN departments d ON e.department_id = d.department_id
JOIN locations  l ON d.location_id     = l.location_id;

4) 페이징과 조인 결합 (ROWNUM 패턴)

Oracle 11g에서 페이징은 인라인 뷰 + ROWNUM을 사용한다.

SELECT *
FROM (
  SELECT x.*, ROWNUM rn
  FROM (
    SELECT e.employee_id, e.first_name, d.department_name, e.hire_date
    FROM employees e
    JOIN departments d ON e.department_id = d.department_id
    ORDER BY e.hire_date DESC
  ) x
  WHERE ROWNUM <= :offset + :limit
)
WHERE rn > :offset;

 

  • INNER vs LEFT: 기준 테이블을 명확히 한다. 기준을 잃으면 건수가 틀어진다.
  • FULL OUTER JOIN은 전체 누락 파악에 유용하나 비용이 클 수 있다.
  • NATURAL JOIN은 컬럼명 의존도가 높아 유지보수에 취약하다. 가급적 지양한다.
  • 조인 후 집계 시 GROUP BY 컬럼을 정확히 지정한다. 의도치 않은 중복행을 경계한다.
  • 11g 페이징은 인라인 뷰 + ROWNUM을 사용한다. ORDER BY는 반드시 가장 안쪽에서 먼저 수행한다.
  • 성능 이슈가 있으면 조인 컬럼의 인덱스, 조인 순서, 통계 최신화, 힌트 사용을 점검한다.