DataBase+SQL

JOIN(조인)

campanula 2023. 6. 19. 17:27

JOIN: 한 개 이상의 테이블에서 데이터를 조회하기 위해서 사용되는 것.

두 개 이상의 테이블을 결합해야만 원하는 결과를 얻을 수 있을 때

 

Equi join 동일 칼럼을 기준으로 조인(inner join simple join)
NinEqui Join 동일 칼럼이 없이 다른 조건을 사용하여 조인
Outer Join 조인 조건에 만족하지 않는 행도 나타낸다.
Self Join 한 테이블 내에서 조인// 마치 서로 다른 테이블인 것 처럼

WHERE절에 명시하는 조건이 FROM절에 명시한 여러 TABLE을 묶는 JOIN조건이 된다. 이러한 JOIN조건은 반도시 묶어야 할 TABLE수보다 하나가 적다. 즉, TABLE 수가 N 개라면 JOIN조건은 N-1이 된다.


1.CARTESIAN PRODUCT OR CROSS JOIN --INNER JOIN

2개 이상의 테이블이 조인될 때 WHERE절에 의해 공통되는 칼럼에 의한 결합이 발생되지 않는 경우 (대부분 사용X, WHERE을 가지지 않아야 해서 경우의 수가 다 나옴)

 

기본적으로 조인은 다음과 같은 규칙을 준수

  1. PRIMARY KEY와 FOREIGN KEY 컬럼을 통한 다른 테이블의 행과 연결
  2. 연결 KEY 사용으로 테이블과 테이블이 결합
  3.  WHERE 절에서 조인 조건을 사용. (조인 조건 개수 = 연결 테이블의 수-1)
  4. 명확성을 위해 칼럼 이름 앞에 테이블명 OR 테이블 별칭을 붙인다. (테이블 별칭.컬럼)

자식 테이블에 외래키(부모키가 중복을 허용하면 안됨.// 기본키 OR 유일키)에 있는 값만이 존재한다고 관계 설정

 

먼저 읽는 테이블을 선행 테이블,뒤에 읽는 테이블을 후행 테이블=> 선행 테이블은 조회할 데이터가 적은 테이블로 선택해야 속도에 유리

 

2.Equi Join(inner join)=> 가장 많이 사용

두 테이블에서 공통적으로 존재하는 칼럼의 값이 일치되는 행을 연결하여 결과를 생성

칼럼명이 같게 되면 혼동이 오기 때문에 칼럼명 앞에  테이블명을 점(.)과 함께 기술

WHERE EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID;
--DEPARTMENT_ID라고만 하면 ORA-00918: 열의 정의가 애매합니다 오류 //테이블이 2개 있는데 어디에 있는 값을 가져올지...
--비교 연산자로 "=" EQUI

 

테이블명이 너무 긴 경우에는 테미블 명에 간단하게 별칭을 부여해서 문장을 간단하게 기술

FROM EMPLOYEES E, DEPARTMENTS D
--이제부터는 테이블명 대신 별칭, 혼합사용X
SELECT E.FIRST_NAME, D.DEPARTMENT_NAME, E.DEPARTMENT_ID
FROM EMPLOYEES E, DEPARTMENTS D
WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID;

3.Non-Equi Join

조인할 테이블 사이에 칼럼의 값이 직접적으로 일치X

--사원명, 급여, 등급
SELECT E.FIRST_NAME, S.GRADE, E.SALARY
FROM EMPLOYEES E, SALARYGRADE S
WHERE E.SALARY BETWEEN S.MINSALARY AND S.MAXSALARY;

4.Outer Join

조인 조건에 만족하지 않는 행들도 나타내기 위해

사용하는 기호는 (+), 조인 조건에서 정보가 부족한 칼럼명 뒤에 위치하게 하면 된다.

--Inner Join// 일치하는 값만
SELECT E.FIRST_NAME, D.DEPARTMENT_ID, D.DEPARTMENT_NAME
FROM EMPLOYEES E, DEPARTMENTS D
WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID
ORDER BY D.DEPARTMENT_ID;
--Outer Join //한쪽의 테이블은 다
--부서 테이블의 데이터는 다 가져옴. 사원은 없으니 NULL
SELECT E.FIRST_NAME, D.DEPARTMENT_ID, D.DEPARTMENT_NAME
FROM EMPLOYEES E, DEPARTMENTS D
WHERE E.DEPARTMENT_ID(+) = D.DEPARTMENT_ID;

 

--2007년도 상반기에 입사한 사원
SELECT EMPLOYEE_ID, FIRST_NAME, HIRE_DATE, DEPARTMENT_ID
FROM EMPLOYEES
WHERE HIRE_DATE BETWEEN '2007.01.01' AND '2007.06.30';

--DEPARTMENT_ID가 NULL값인 것이 사라짐. 부서 배정을 안받음
SELECT E.EMPLOYEE_ID, E.FIRST_NAME, E.HIRE_DATE, D.DEPARTMENT_NAME
FROM EMPLOYEES E, DEPARTMENTS D
WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID AND HIRE_DATE BETWEEN '2007.01.01' AND '2007.06.30';

--부서가 적으므로 부서 쪽에 (+)
SELECT EMPLOYEE_ID, FIRST_NAME, HIRE_DATE, D.DEPARTMENT_NAME
FROM EMPLOYEES E, DEPARTMENTS D
WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID(+) AND HIRE_DATE BETWEEN '2007.01.01' AND '2007.06.30';

 

5.Self Join

자기 자신과 조인을 맺는 것. 서로 다른 테이블인 것처럼 인식할 수 있도록 하기 위해서 별칭을 사용

SELECT WORK.FIRST_NAME 사원명, MANAGER.FIRST_NAME 매니저명
FROM EMPLOYEES WORK, EMPLOYEES MANAGER
WHERE WORK.MANAGER_ID = MANAGER.EMPLOYEE_ID;
SELECT CONCAT(CONCAT(CONCAT(RPAD(WORK.FIRST_NAME, 11, ' '), '의 매니저는 '), MANAGER.FIRST_NAME), '이다.') AS " 그 사원의 매니저"
FROM EMPLOYEES WORK, EMPLOYEES MANAGER
WHERE WORK.MANAGER_ID = MANAGER.EMPLOYEE_ID;

6.ANSI Join

대부분의 상용 데이터 베이스  시스템에서 표준 언어

다른 DBMS와의 호환성을 위해 ANSI 조인을 사용하는 것이 좋다.

 

1)ANSI Cross Join

SELECT * FROM EMPLOYEES CROSS JOIN DEPARTMENTS;

2)ANSI Inner Join

, 대신 INNER JOIN

JOIN만 쓰면 기본값 INNER JOIN

INNER JOIN - ON-

SELECT * FROM TABLE1 INNER JOIN TABLE2
ON TABEL1.COLUMN1 = TABLE2.COLUMN2

SELECT 컬럼
FROM 테이블 INNER JOIN 테이블
ON 조인 조건식

--2개 연결하고 나머지 하나 연결, 3번째 테이블과 앞에 있는 테이블
SELECT 컬럼
FROM 테이블1 INNER JOIN 테이블2
ON 테이블1.컬럼 = 테이블2.컬럼
INNER JOIN 테이블3
ON 테이블1.컬럼=테이블3.컬럼
--사원 테이블(EMPLOYEES)과 직무 테이블(JOBS)=> 공통 컬럼: JOB_ID
--사원 테이블(EMPLOYEES)과 부서 테이블(DEPARTMENTS)=>공통 컬럼: DEPARMENT_ID
--사원명, 직무ID, 직무명(JOB_TITLE), 부서번호, 부서명
SELECT E.FIRST_NAME, E.JOB_ID, J.JOB_TITLE, E.DEPARTMENT_ID, D.DEPARTMENT_NAME
FROM EMPLOYEES E INNER JOIN JOBS J ON E.JOB_ID = J.JOB_ID
                 INNER JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;

-USING: 두 테이블 간의 조인 조건에 사용되는 칼럼이 같다면 ON 대신 USING을 사용 (ON을 써서 명확히 명시)

SELECT * FROM TABLE1 INNER JOIN TABLE2
USING(공통칼럼)

 

4)ANSI Outer Join

부족한 쪽이 아니라 전체를 가져올 TABLE쪽을 기준으로 LEFT, RIGHT를 설정

SELECT * FROM TABLE1 [LEFT|RIGHT|FULL] OUTER JOIN TABLE2 ON 조건문