본 게시글은 아래의 글을 필사하였습니다.
http://tcpschool.com/mysql/mysql_multipleTable_join
http://tcpschool.com/mysql/mysql_multipleTable_union
JOIN
JOIN은 데이터베이스 내의 여러 테이블에서 가져온 레코드를 조합하여 하나의 테이블이나 결과 집합으로 표현해 줍니다. 이러한 JOIN은 보통 SELECT 문과 함께 자주 사용됩니다. 표준 SQL에서는 레코드를 조합하는 방식에 따라 JOIN을 다음과 같이 구분합니다.
- INNER JOIN
- LEFT JOIN
- RIGHT JOIN
예제에서 쓰일 예시 테이블입니다.
RESERVATION
RID | NAME | RESERVE_DATE | ROOM_NUM |
1 | 홍길동 | 2021-01-05 | 2014 |
2 | 임꺽정 | 2021-02-12 | 918 |
3 | 장길산 | 2021-01-16 | 1208 |
4 | 홍길동 | 2021-03-17 | 504 |
CUSTOMER
UID | NAME | AGE | ADDRESS |
1 | 홍길동 | 17 | 서울 |
2 | 임꺽정 | 11 | 인천 |
3 | 장길산 | 13 | 서울 |
4 | 전우치 | 17 | 수원 |
INNER JOIN
INNER JOIN은 ON 절과 함께 사용되며, ON 절의 조건을 만족하는 데이터만을 가져옵니다.
SELECT * FROM RESERVATION INNER JOIN CUSTOMER ON RESERVATION.NAME = CUSTOMER.NAME;
SELECT * FROM RESERVATION JOIN CUSTOMER ON RESERVATION.NAME = CUSTOMER.NAME
ON 절에서는 WHERE 절에서 사용할 수 있는 모든 조건을 사용할 수 있습니다. 표준 SQL과 달리 MYSQL에서는 JOIN, INNER JOIN, CROSS JOIN이 모두 같은 의미로 사용됩니다.
실행 결과 :
RID | NAME | RESERVE_DATE | ROOM_NUM | UID | NAME | AGE | ADDRESS |
1 | 홍길동 | 2021-01-05 | 2014 | 1 | 홍길동 | 17 | 서울 |
4 | 홍길동 | 2121-03-17 | 504 | 1 | 홍길동 | 17 | 서울 |
2 | 임꺽정 | 2021-02-12 | 918 | 2 | 임꺽정 | 11 | 인천 |
3 | 장길산 | 2021-01-16 | 1208 | 3 | 장길산 | 13 | 서울 |
INNER JOIN 의 결과를 벤 다이어그램으로 나타내면 다음과 같습니다.
INNER JOIN 의 경우에는 앞서 살펴본 표준 SQL방식과는 별도로 MYSQL에서만 사용할 수 있는 방식이 따로 존재합니다. 다음 예제는 앞서 살펴본 INNER JOIN 예제와 같은 실행결과를 보여줍니다.
SELECT * FROM RESERVATION, CUSTOMER WHERE RESERVAION.NAME = CUSTOMER.NAME;
위의 예제처럼 테이블의 이름이 길거나 복잡한 경우에는 별칭(alias)을 사용하여 SQL 구문을 간략하게 할 수 있습니다.
SELECT * FROM RESERVATION AS R, CUSTOMER AS C WHERE R.NAME = C.NAME;
LEFT JOIN
LEFT JOIN은 첫 번째 테이블을 기준으로, 두 번째 테이블을 조합하는 JOIN입니다. 이 때 ON 절의 조건을 만족하지 않는 경우에는 첫 번째 테이블의 필드 값은 그대로 가져옵니다. 하지만 해당 레코드의 두 번째 테이블의 필드 값은 모두 NULL로 표시됩니다.
다음 예제는 RESERVATION 테이블의 NAME 필드를 기준으로 CUSTOMER 테이블의 NAME 필드와 일치하는 레코드만을 LEFT JOIN으로 가져온 후, 그 중에서 RESERVE_DATE 필드의 값이 2021년 02월 01일 이후인 레코드만을 선택하는 예제입니다.
SELECT *
FROM RESERVATION LEFT JOIN CUSTOMER
ON RESERVATION.NAME = CUSTOMER.NAME
WHERE RESERVE_DATE > '2021-02-01';
실행 결과 :
RID | NAME | RESERVE_DATE | ROOM_NUM | UID | NAME | AGE | ADDRESS |
4 | 홍길동 | 2021-03-17 | 504 | 1 | 홍길동 | 17 | 서울 |
2 | 임꺽정 | 2021-02-12 | 918 | 2 | 임꺽정 | 11 | 인천 |
위의 예제에서 두 개의 NAME 값이 일치하면, INNER JOIN과 같이 두 테이블의 모든 필드를 그대로 가져옵니다. 하지만 두 개의 NAME 값이 일치하지 않는 경우에는 CUSTOMER 테이블의 모든 필드는 NULL로 표시됩니다.
LEFT JOIN 의 결과를 벤 다이어그램으로 나타내면 다음과 같습니다.
RIGHT JOIN
RIGHT JOIN은 LEFT JOIN 과는 반대로 두 번째 테이블을 기준으로, 첫 번째 테이블을 조합하는 JOIN입니다.
이 때 ON 절의 조건을 만족하지 않는 경우에는 두 번째 테이블의 필드 값을 그대로 가져옵니다. 하지만 해당 레코드의 첫 번째 테이블의 필드 값은 모두 NULL로 표시됩니다.
다음 예제는 CUSTOMER 테이블의 NAME 필드를 기준으로 RESERVATION 테이블의 NAME 필드와 일치하는 레코드만을 RIGHT JOIN으로 가져오는 예제입니다.
SELECT *
FROM RESERVATION RIGHT JOIN CUSTOMER
ON RESERVATION.NAME = CUSTOMER.NAME;
실행 결과 :
UID | NAME | AGE | ADDRESS | RID | NAME | RESERVE_DATE | ROOM_NUM |
1 | 홍길동 | 17 | 서울 | 1 | 홍길동 | 2021-01-05 | 2014 |
1 | 홍길동 | 17 | 서울 | 4 | 홍길동 | 2021-03-17 | 504 |
2 | 임꺽정 | 11 | 인천 | 2 | 임꺽정 | 2021-02-12 | 918 |
3 | 장길산 | 13 | 서울 | 3 | 장길산 | 2021-01-16 | 1208 |
위의 예제에서 두 개의 NAME 값이 일치하면, INNER JOIN 과 같이 두 테이블의 모든 필드를 그대로 가져옵니다. 하지만 두 개의 NAME 값이 일치하지 않는 경우에는 RESERVATION 테이블의 모든 필드는 NULL로 표시됩니다.
RIGHT JOIN 의 결과를 벤 다이어그램으로 나타내면 다음과 같습니다.
UNION
UNION은 여러 개의 SELECT 문의 결과를 하나의 테이블이나 결과 집합으로 표현할 때 사용합니다. 이 때 각각의 SELECT 문으로 선택된 필드의 개수와 타입은 모두 같아야 하며, 필드의 순서 또한 같아야 합니다.
다음 예제는 두 SELECT 문의 결과를 UNION을 이용하여 하나의 테이블로 출력하는 예제입니다.
SELECT NAME FROM RESERVATION UNION SELECT NAME FORM CUSTOMER;
실행 결과 :
NAME |
홍길동 |
임꺽정 |
장길산 |
위의 예제에서 두 SELECT 문의 결과는 하나로 합쳐져서 출력됩니다. 이 때 두 SELECT 문의 결과에서 중복된 레코드인 '홍길동'은 한 번만 표시됩니다.
UNION ALL
위의 예제처럼 UNION은 DISTINCT 키워드를 따로 명시하지 않아도 기본적으로 중복되는 레코드를 제거합니다. 따라서 이렇게 중복되는 레코드까지 모두 출력하고 싶다면, ALL 키워드를 사용해야 합니다.
다음 예제는 두 SELECT 문의 결과를 UNION ALL을 이용하여 하나의 테이블로 출력하는 예제입니다.
SELECT NAME FROM RESERVATION UNION ALL SELECT NAME FROM CUSTOMER;
실행 결과 :
NAME |
홍길동 |
임꺽정 |
장길산 |
홍길동 |
홍길동 |
임꺽정 |
장길산 |
위의 예제에서 두 SELECT 문의 결과는 하나로 합쳐져서 출력됩니다. 이 때 두 SELECT 문의 결과는 중복된 레코드까지 모두 표시합니다.
추가로 예시를 만들어 보았다.
2021년 2월 1일 이후의 예약을 다음의 정보들만 포함하여 확인하라.
[예약번호, 이름, 주소, 날짜, 방 번호]
SELECT R.ID, R.NAME, C.ADDRESS, R.RESERVE_DATE, R.ROOM_NUM
FROM RESERVATION AS R LEFT JOIN CUSTOMER AS C
ON R.NAME = C.NAME
WHERE RESERVE_DATE > '2021-02-01';
'필사적 필사' 카테고리의 다른 글
데이터베이스 정규화와 이상현상 (2) | 2021.06.16 |
---|---|
computed와 watch (0) | 2020.04.24 |
Vue 인스턴스 (0) | 2020.04.24 |
상태 | Vuex (0) | 2020.04.24 |
시작하기 | Vuex (0) | 2020.04.24 |