[MySQL] INNER JOIN, OUTER JOIN, CROSS JOIN, SELF JOIN
JOIN이란 두 개의 테이블을 묶어서 하나의 결과로 보여주는 것을 말한다.
두 테이블의 조인을 위해서는 테이블이 일대다 관계로 연결되어야 한다.
예를 들면, 어느 쇼핑몰의 회원은 유니크한 아이디를 갖는다. 그 회원은 상품 구매는 여러번 할 수 있어서 구매 이력은 여러개를 갖는다. 따라서 쇼핑몰의 회원별 구매 이력은 회원 테이블과 구매이력을 조인하여 보여줄 수 있다.
내부 조인 (INNER JOIN)
내부 조인의 경우 값이 있는 데이터를 조인하여 보여준다.
내부 조인의 형식은 다음과 같다.
INNER JOIN의 경우 그냥 JOIN이라고만 써도 INNER JOIN이라고 인식한다.
SELECT 열 목록
FROM 테이블1
INNER JOIN 테이블2
ON 조인 조건
WHERE 검색 조건
예제
USE market_db;
SELECT buy.mem_id, mem_name, prod_name, CONCAT(phone1, phone2) AS '연락처'
FROM buy
INNER JOIN member
ON buy.mem_id = member.mem_id;
외부 조인 (OUTER JOIN)
외부 조인의 경우 값이 없는 데이터도 조인하여 보여줄 수 있다.
외부 조인은 LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN이 있다.
LEFT, RIGHT, FULL은 기준이 되는 테이블의 위치를 말하며, 기준이 아닌 테이블에 값이 없어도 기준 테이블 기준으로 데이터가 조회된다.
FULL OUTER JOIN은 한 쪽에라도 데이터가 존재하면 조회되는데, MySQL에서는 FULL OUTER JOIN을 지원하지 않으므로 비슷하게 구현하고 싶다면 UNION을 사용하면 된다.
LEFT OUTER JOIN 예제


아래 쿼리에서 LEFT OUTER JOIN을 사용했으므로 JOIN 좌측에 명시한 테이블인 member가 기준 테이블이며, buy에 member의 mem_id와 일치하는 mem_id가 없어도 해당 행에는 NULL로 조회된다.

USE market_db;
SELECT member.mem_id, member.mem_name, buy.prod_name, buy.price, buy.amount
FROM member
LEFT OUTER JOIN buy
ON buy.mem_id = member.mem_id
ORDER BY member.mem_id, buy.prod_name;
RIGHT OUTER JOIN 예제
위 LEFT OUTER JOIN과 동일한 결과를 얻는 RIGHT OUTER JOIN 쿼리는 다음과 같다.
마찬가지로 RIGHT OUTER JOIN을 사용했으므로 JOIN 우측에 명시한 member가 기준 테이블이 된다.

SELECT member.mem_id, member.mem_name, buy.prod_name, buy.price, buy.amount
FROM buy
RIGHT OUTER JOIN member
ON buy.mem_id = member.mem_id
ORDER BY member.mem_id, buy.prod_name;
상호 조인 (CROSS JOIN)
CROSS JOIN은 한쪽 테이블의 행과 다른쪽 테이블의 모든 행을 조인시키는 기능이다.
따라서 결과의 전체 행 개수는 두 테이블의 각 행의 개수를 곱한 개수가 된다.
모든 내용을 조인하므로 결과의 내용이 의미를 갖고있다고 보기 어려우며, 주로 테스트를 위해 대용량 데이터를 생성하는데 사용한다.
CROSS JOIN은 ON 조건 없이 사용하면 된다.
예제

자체 조인 (SELF JOIN)
SELF JOIN은 위의 다른 조인들과 다르게 2개 테이블이 아닌 자기 자신을 조인할 때 사용한다.
SELF JOIN의 형식은 아래와 같다. 테이블 1개를 사용하지만 다른 별칭을 사용하여 서로 다른테이블인 것처럼 사용한다.
SELECT 열 목록
FROM 테이블명 별칭1
INNER JOIN 테이블명 별칭2
ON 조인 조건
WHERE 검색 조건
예제
사원의 정보가 들어있는 emp_table이라는 단일 테이블을 SELF JOIN하여 특정 직원의 직속상관(manager)의 번호를 조회한다.

USE market_db;
CREATE TABLE emp_table (emp CHAR(4), manager CHAR(4), phone VARCHAR(8));
INSERT INTO emp_table VALUES('대표', NULL, '0000');
INSERT INTO emp_table VALUES('영업이사', '대표', '1111');
INSERT INTO emp_table VALUES('관리이사', '대표', '2222');
INSERT INTO emp_table VALUES('정보이사', '대표', '3333');
INSERT INTO emp_table VALUES('영업과장', '영업이사', '1111-1');
INSERT INTO emp_table VALUES('경리부장', '관리이사', '2222-1');
INSERT INTO emp_table VALUES('인사부장', '관리이사', '2222-2');
INSERT INTO emp_table VALUES('개발팀장', '정보이사', '3333-1');
INSERT INTO emp_table VALUES('개발주임', '정보이사', '3333-1-1');
SELECT A.emp "직원" , B.emp "직속상관", B.phone "직속상관연락처"
FROM emp_table A
INNER JOIN emp_table B
ON A.manager = B.emp
WHERE A.emp = '경리부장';