편집 요약 없음 |
편집 요약 없음 |
||
(같은 사용자의 중간 판 4개는 보이지 않습니다) | |||
1번째 줄: | 1번째 줄: | ||
=== Oracle 테이블 조인 (Table Join) === | |||
{{요점 | |||
|내용=조인이란? | |||
> 여러 테이블에서 관련된 데이터를 **하나의 결과로 결합**해서 보여주는 SQL 기능입니다. | > 여러 테이블에서 관련된 데이터를 **하나의 결과로 결합**해서 보여주는 SQL 기능입니다. | ||
11번째 줄: | 8번째 줄: | ||
예: 직원 정보는 `EMPLOYEES`, 부서 정보는 `DEPARTMENTS`에 있을 때 | 예: 직원 정보는 `EMPLOYEES`, 부서 정보는 `DEPARTMENTS`에 있을 때 | ||
👉 직원 이름 + 부서 이름을 함께 보여주고 싶을 때 조인을 사용합니다. | 👉 직원 이름 + 부서 이름을 함께 보여주고 싶을 때 조인을 사용합니다. | ||
}} | |||
---- | |||
==== 예제 테이블 ==== | |||
<source lang=sql> | |||
-- EMPLOYEES 테이블 | -- EMPLOYEES 테이블 | ||
| EMP_ID | NAME | DEPT_ID | | | EMP_ID | NAME | DEPT_ID | | ||
30번째 줄: | 26번째 줄: | ||
| 20 | IT | | | 20 | IT | | ||
| 30 | Marketing | | | 30 | Marketing | | ||
</source> | |||
=== 조인 종류 === | |||
{| class="wikitable" | {| class="wikitable" | ||
! 조인 종류 || 설명 | ! 조인 종류 || 설명 | ||
51번째 줄: | 45번째 줄: | ||
|} | |} | ||
==== INNER JOIN ==== | |||
<source lang=sql> | |||
SELECT E.EMP_ID, E.NAME, D.DEPT_NAME | SELECT E.EMP_ID, E.NAME, D.DEPT_NAME | ||
FROM EMPLOYEES E | FROM EMPLOYEES E | ||
INNER JOIN DEPARTMENTS D | INNER JOIN DEPARTMENTS D | ||
ON E.DEPT_ID = D.DEPT_ID; | ON E.DEPT_ID = D.DEPT_ID; | ||
</source> | |||
{| class="wikitable" | {| class="wikitable" | ||
! EMP_ID || NAME || DEPT_NAME | |||
|- | |||
| 101 || Alice || HR | |||
|- | |||
| 102 || Bob || IT | |||
|- | |||
| 103 || Charlie || HR | |||
|} | |||
==== LEFT OUTER JOIN ==== | |||
<source lang=sql> | |||
SELECT E.EMP_ID, E.NAME, D.DEPT_NAME | SELECT E.EMP_ID, E.NAME, D.DEPT_NAME | ||
FROM EMPLOYEES E | FROM EMPLOYEES E | ||
LEFT OUTER JOIN DEPARTMENTS D | LEFT OUTER JOIN DEPARTMENTS D | ||
ON E.DEPT_ID = D.DEPT_ID; | ON E.DEPT_ID = D.DEPT_ID; | ||
</source> | |||
* `EMPLOYEES`의 모든 직원은 다 나오고, | * `EMPLOYEES`의 모든 직원은 다 나오고, | ||
* 일치하지 않는 부서가 있으면 `DEPT_NAME`은 NULL | * 일치하지 않는 부서가 있으면 `DEPT_NAME`은 NULL | ||
==== RIGHT OUTER JOIN ==== | |||
<source lang=sql> | |||
SELECT E.EMP_ID, E.NAME, D.DEPT_NAME | SELECT E.EMP_ID, E.NAME, D.DEPT_NAME | ||
FROM EMPLOYEES E | FROM EMPLOYEES E | ||
RIGHT OUTER JOIN DEPARTMENTS D | RIGHT OUTER JOIN DEPARTMENTS D | ||
ON E.DEPT_ID = D.DEPT_ID; | ON E.DEPT_ID = D.DEPT_ID; | ||
</source> | |||
* `DEPARTMENTS`의 모든 부서는 다 나오고, | * `DEPARTMENTS`의 모든 부서는 다 나오고, | ||
* 직원이 없는 부서는 `EMP_ID`, `NAME`이 NULL | * 직원이 없는 부서는 `EMP_ID`, `NAME`이 NULL | ||
==== FULL OUTER JOIN ==== | |||
<source lang=sql> | |||
SELECT E.EMP_ID, E.NAME, D.DEPT_NAME | SELECT E.EMP_ID, E.NAME, D.DEPT_NAME | ||
FROM EMPLOYEES E | FROM EMPLOYEES E | ||
FULL OUTER JOIN DEPARTMENTS D | FULL OUTER JOIN DEPARTMENTS D | ||
ON E.DEPT_ID = D.DEPT_ID; | ON E.DEPT_ID = D.DEPT_ID; | ||
</source> | |||
* `EMPLOYEES`, `DEPARTMENTS` 둘 다 포함 | * `EMPLOYEES`, `DEPARTMENTS` 둘 다 포함 | ||
* 한쪽에만 데이터가 있으면 다른 쪽은 NULL | * 한쪽에만 데이터가 있으면 다른 쪽은 NULL | ||
==== CARTESIAN JOIN (CROSS JOIN) ==== | |||
<source lang=sql> | |||
SELECT E.EMP_ID, E.NAME, D.DEPT_NAME | SELECT E.EMP_ID, E.NAME, D.DEPT_NAME | ||
FROM EMPLOYEES E | FROM EMPLOYEES E | ||
CROSS JOIN DEPARTMENTS D; | CROSS JOIN DEPARTMENTS D; | ||
</source> | |||
* 조인 조건 없이 **모든 행을 조합** | * 조인 조건 없이 **모든 행을 조합** | ||
128번째 줄: | 107번째 줄: | ||
{| class="wikitable" | {| class="wikitable" | ||
! EMP_ID || NAME || DEPT_NAME | |||
|- | |||
| 101 || Alice || HR | |||
|- | |||
| 101 || Alice || IT | |||
|- | |||
| 101 || Alice || Marketing | |||
|- | |||
| 102 || Bob || HR | |||
|- | |||
| 102 || Bob || IT | |||
|- | |||
| ... || ... || ... | |||
|} | |||
> ❗ 주의: **WHERE 조건 없이 CROSS JOIN을 쓰면 큰 결과가 나올 수 있어 조심해야 합니다.** [[카테시안 조인]] | |||
> ❗ 주의: **WHERE 조건 없이 CROSS JOIN을 쓰면 큰 결과가 나올 수 있어 조심해야 합니다.** | |||
==== ANTI JOIN (조건에 부합하지 않는 데이터만) ==== | |||
<source lang=sql> | |||
SELECT * | SELECT * | ||
FROM DEPARTMENTS D | FROM DEPARTMENTS D | ||
154번째 줄: | 131번째 줄: | ||
SELECT 1 FROM EMPLOYEES E WHERE E.DEPT_ID = D.DEPT_ID | SELECT 1 FROM EMPLOYEES E WHERE E.DEPT_ID = D.DEPT_ID | ||
); | ); | ||
</source> | |||
* **직원이 없는 부서만 조회**하는 예제입니다. | * **직원이 없는 부서만 조회**하는 예제입니다. | ||
{| class="wikitable" | {| class="wikitable" | ||
! DEPT_ID || DEPT_NAME | |||
|- | |||
| 30 || Marketing | |||
|} | |||
> ✅ 실무에서 **특정 값이 존재하지 않는 경우**를 찾을 때 많이 사용합니다. | > ✅ 실무에서 **특정 값이 존재하지 않는 경우**를 찾을 때 많이 사용합니다. | ||
=== 요점정리 === | |||
{| class="wikitable" | {| class="wikitable" | ||
! 조인 종류 || 대표 SQL 구문 || 출력 대상 | |||
|- | |||
| - | | INNER JOIN || A INNER JOIN B ON 조건 || A와 B 모두 조건에 맞는 데이터만 | ||
| INNER JOIN | |- | ||
| - | | LEFT OUTER JOIN || A LEFT OUTER JOIN B ON 조건 || A는 모두, B는 맞는 것만 | ||
| LEFT OUTER JOIN | |- | ||
| - | | RIGHT OUTER JOIN || A RIGHT OUTER JOIN B ON 조건 || B는 모두, A는 맞는 것만 | ||
| RIGHT OUTER JOIN | |- | ||
| - | | FULL OUTER JOIN || A FULL OUTER JOIN B ON 조건 || A와 B 모두 포함 | ||
| FULL OUTER JOIN | |- | ||
| - | | CROSS JOIN || A CROSS JOIN B || 모든 조합 (곱집합) | ||
| CROSS JOIN | |- | ||
| - | | ANTI JOIN || WHERE NOT EXISTS (서브쿼리) || 조건에 부합하지 않는 데이터 | ||
| ANTI JOIN | |} | ||
| } | |||
195번째 줄: | 165번째 줄: | ||
https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Joins.html#GUID-39081984-8D38-4D64-A847-AA43F515D460 | https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Joins.html#GUID-39081984-8D38-4D64-A847-AA43F515D460 | ||
2025년 5월 14일 (수) 01:27 기준 최신판
Oracle 테이블 조인 (Table Join)
menu_book 조인이란?
> 여러 테이블에서 관련된 데이터를 **하나의 결과로 결합**해서 보여주는 SQL 기능입니다.
예: 직원 정보는 `EMPLOYEES`, 부서 정보는 `DEPARTMENTS`에 있을 때
👉 직원 이름 + 부서 이름을 함께 보여주고 싶을 때 조인을 사용합니다.예제 테이블
-- EMPLOYEES 테이블 | EMP_ID | NAME | DEPT_ID | |--------|---------|---------| | 101 | Alice | 10 | | 102 | Bob | 20 | | 103 | Charlie | 10 | -- DEPARTMENTS 테이블 | DEPT_ID | DEPT_NAME | |---------|------------| | 10 | HR | | 20 | IT | | 30 | Marketing |
조인 종류
조인 종류 | 설명 |
---|---|
INNER JOIN | 두 테이블에서 일치하는 값이 있는 행만 보여줌 |
LEFT OUTER JOIN | 왼쪽 테이블은 무조건 모두 출력, 오른쪽에 일치하는 값이 없으면 NULL |
RIGHT OUTER JOIN | 오른쪽 테이블은 무조건 모두 출력, 왼쪽에 일치하는 값이 없으면 NULL |
FULL OUTER JOIN | 양쪽 테이블을 모두 포함, 일치하지 않으면 NULL |
CROSS JOIN (카테시안 조인) | 두 테이블의 모든 행 조합을 출력 (곱집합) |
ANTI JOIN | 조건에 맞지 않는 행만 보여줌 (EXISTS가 아닌 NOT EXISTS 조건) |
INNER JOIN
SELECT E.EMP_ID, E.NAME, D.DEPT_NAME FROM EMPLOYEES E INNER JOIN DEPARTMENTS D ON E.DEPT_ID = D.DEPT_ID;
EMP_ID | NAME | DEPT_NAME |
---|---|---|
101 | Alice | HR |
102 | Bob | IT |
103 | Charlie | HR |
LEFT OUTER JOIN
SELECT E.EMP_ID, E.NAME, D.DEPT_NAME FROM EMPLOYEES E LEFT OUTER JOIN DEPARTMENTS D ON E.DEPT_ID = D.DEPT_ID;
- `EMPLOYEES`의 모든 직원은 다 나오고,
- 일치하지 않는 부서가 있으면 `DEPT_NAME`은 NULL
RIGHT OUTER JOIN
SELECT E.EMP_ID, E.NAME, D.DEPT_NAME FROM EMPLOYEES E RIGHT OUTER JOIN DEPARTMENTS D ON E.DEPT_ID = D.DEPT_ID;
- `DEPARTMENTS`의 모든 부서는 다 나오고,
- 직원이 없는 부서는 `EMP_ID`, `NAME`이 NULL
FULL OUTER JOIN
SELECT E.EMP_ID, E.NAME, D.DEPT_NAME FROM EMPLOYEES E FULL OUTER JOIN DEPARTMENTS D ON E.DEPT_ID = D.DEPT_ID;
- `EMPLOYEES`, `DEPARTMENTS` 둘 다 포함
- 한쪽에만 데이터가 있으면 다른 쪽은 NULL
CARTESIAN JOIN (CROSS JOIN)
SELECT E.EMP_ID, E.NAME, D.DEPT_NAME FROM EMPLOYEES E CROSS JOIN DEPARTMENTS D;
- 조인 조건 없이 **모든 행을 조합**
- EMPLOYEES가 3행, DEPARTMENTS가 3행이면 → 결과는 9행
EMP_ID | NAME | DEPT_NAME |
---|---|---|
101 | Alice | HR |
101 | Alice | IT |
101 | Alice | Marketing |
102 | Bob | HR |
102 | Bob | IT |
... | ... | ... |
> ❗ 주의: **WHERE 조건 없이 CROSS JOIN을 쓰면 큰 결과가 나올 수 있어 조심해야 합니다.** 카테시안 조인
ANTI JOIN (조건에 부합하지 않는 데이터만)
SELECT * FROM DEPARTMENTS D WHERE NOT EXISTS ( SELECT 1 FROM EMPLOYEES E WHERE E.DEPT_ID = D.DEPT_ID );
- **직원이 없는 부서만 조회**하는 예제입니다.
DEPT_ID | DEPT_NAME |
---|---|
30 | Marketing |
> ✅ 실무에서 **특정 값이 존재하지 않는 경우**를 찾을 때 많이 사용합니다.
요점정리
조인 종류 | 대표 SQL 구문 | 출력 대상 |
---|---|---|
INNER JOIN | A INNER JOIN B ON 조건 | A와 B 모두 조건에 맞는 데이터만 |
LEFT OUTER JOIN | A LEFT OUTER JOIN B ON 조건 | A는 모두, B는 맞는 것만 |
RIGHT OUTER JOIN | A RIGHT OUTER JOIN B ON 조건 | B는 모두, A는 맞는 것만 |
FULL OUTER JOIN | A FULL OUTER JOIN B ON 조건 | A와 B 모두 포함 |
CROSS JOIN | A CROSS JOIN B | 모든 조합 (곱집합) |
ANTI JOIN | WHERE NOT EXISTS (서브쿼리) | 조건에 부합하지 않는 데이터 |