본문 바로가기
MySQL

MySQL 연산

by FraisGout 2020. 7. 2.

JOIN

JOIN은 데이터베이스 내의 여러 테이블에서 가져온 레코드를 조합하여 하나의 테이블이나 결과 집합으로 표현해 줍니다.

 

이러한 JOIN은 보통 SELECT 문과 함께 자주 사용됩니다.

 

 

 

표준 SQL에서는 레코드를 조합하는 방식에 따라 JOIN을 다음과 같이 구분합니다.

 

 

 

1. INNER JOIN

 

2. LEFT JOIN

 

3. RIGHT JOIN

 

INNER JOIN

INNER JOINON 절과 함께 사용되며, ON 절의 조건을 만족하는 데이터만을 가져옵니다.

 

문법

1. 첫번째테이블이름

 

INNER JOIN 두번째테이블이름

 

ON 조건

 

2. 첫번째테이블이름

 

JOIN 두번째테이블이름

 

ON 조건

 

 

 

ON 절에서는 WHERE 절에서 사용할 수 있는 모든 조건을 사용할 수 있습니다.

 

표준 SQL과는 달리 MySQL에서는 JOIN, INNER JOIN, CROSS JOIN이 모두 같은 의미로 사용됩니다.

 

 

 

다음 예제는 Reservation 테이블의 Name 필드와 Customer 테이블의 Name 필드가 서로 일치하는 레코드만을 INNER JOIN으로 가져오는 예제입니다.

 

예제

1. SELECT *

 

FROM Reservation

 

INNER JOIN Customer

 

ON Reservation.Name = Customer.Name;

 

2. SELECT *

 

FROM Reservation

 

JOIN Customer

 

ON Reservation.Name = Customer.Name;

MySQL에서는 위의 두 쿼리가 모두 같은 실행 결과를 보여줍니다.

위 예제의 실행 결과처럼 JOIN의 결과는 하나의 테이블 형태로 반환됩니다.

 

INNER JOIN의 경우에는 앞서 살펴본 표준 SQL 방식과는 별도로 MySQL에서만 사용할 수 있는 방식이 따로 존재합니다.

 

다음 예제는 앞서 살펴본 INNER JOIN 예제와 같은 실행 결과를 보여줍니다.

 

예제

SELECT *

 

FROM Reservation, Customer

 

WHERE Reservation.Name = Customer.Name;

 

 

 

위의 예제처럼 테이블의 이름이 길거나 복잡한 경우에는 별칭(alias)을 사용하여 SQL 구문을 간략화할 수 있습니다.

 

 

 

다음 예제는 앞의 예제를 별칭(alias)을 사용하여 간략화한 예제입니다.

 

예제

SELECT *

 

FROM Reservation AS r, Customer AS c

 

WHERE r.Name = c.Name;

 

LEFT JOIN

LEFT JOIN은 첫 번째 테이블을 기준으로, 두 번째 테이블을 조합하는 JOIN입니다.

 

 

 

이때 ON 절의 조건을 만족하지 않는 경우에는 첫 번째 테이블의 필드 값은 그대로 가져옵니다.

 

하지만 해당 레코드의 두 번째 테이블의 필드 값은 모두 NULL로 표시됩니다.

 

문법

첫번째테이블이름

 

LEFT JOIN 두번째테이블이름

 

ON 조건

 

 

 

ON 절에서는 WHERE 절에서 사용할 수 있는 모든 조건을 사용할 수 있습니다.

 

 

 

다음 예제는 Reservation 테이블의 Name 필드를 기준으로 Customer 테이블의 Name 필드와 일치하는 레코드만을 LEFT JOIN으로 가져온 후, 그 중에서 ReserveDate 필드의 값이 20160201일 이후인 레코드만을 선택하는 예제입니다.

 

예제

SELECT *

 

FROM Reservation

 

LEFT JOIN Customer

 

ON Reservation.Name = Customer.Name

 

WHERE ReserveDate > '2016-02-01';

위의 예제에서 두 개의 Name 값이 일치하면, INNER JOIN과 같이 두 테이블의 모든 필드를 그대로 가져옵니다.

 

하지만 두 개의 Name 값이 일치하지 않는 경우에는 Customer 테이블의 모든 필드를 NULL로 표시됩니다.

 

RIGHT JOIN

RIGHT JOINLEFT 조인과는 반대로 두 번째 테이블을 기준으로, 첫 번째 테이블을 조합하는 JOIN입니다.

 

 

 

이때 ON 절의 조건을 만족하지 않는 경우에는 두 번째 테이블의 필드 값은 그대로 가져옵니다.

 

하지만 해당 레코드의 첫 번째 테이블의 필드 값은 모두 NULL로 표시됩니다.

 

문법

첫번째테이블이름

 

LEFT JOIN 두번째테이블이름

 

ON 조건

 

 

 

ON 절에서는 WHERE 절에서 사용할 수 있는 모든 조건을 사용할 수 있습니다.

 

 

 

다음 예제는 Customer 테이블의 Name 필드를 기준으로 Reservation 테이블의 Name 필드와 일치하는 레코드만을 RIGHT JOIN으로 가져오는 예제입니다.

 

예제

SELECT *

 

FROM Reservation

 

RIGHT JOIN Customer

 

ON Reservation.Name = Customer.Name;

위의 예제에서 두 개의 Name 값이 일치하면, INNER JOIN과 같이 두 테이블의 모든 필드를 그대로 가져옵니다.

 

하지만 두 개의 Name 값이 일치하지 않는 경우에는 Reservation 테이블의 모든 필드를 NULL로 표시됩니다.

 

UNION

UNION은 여러 개의 SELECT 문의 결과를 하나의 테이블이나 결과 집합으로 표현할 때 사용합니다.

 

이때 각각의 SELECT 문으로 선택된 필드의 개수와 타입은 모두 같아야 하며, 필드의 순서 또한 같아야 합니다.

 

 

 

SELECT 문에 UNION을 적용하는 문법은 다음과 같습니다.

 

문법

SELECT 필드이름

 

FROM 테이블이름

 

UNION

 

SELECT 필드이름

 

FROM 테이블이름

 

 

 

다음 예제는 두 SELECT 문의 결과를 UNION을 이용하여 하나의 테이블로 출력하는 예제입니다.

 

예제

SELECT Name

 

FROM Reservation

 

UNION

 

SELECT Name

 

FROM Customer;

위의 예제에서 두 SELECT 문의 결과는 하나로 합쳐져서 출력됩니다.

 

이때 두 SELECT 문의 결과에서 중복된 레코드인 '홍길동'은 한 번만 표시합니다.

 

UNION ALL

위의 예제처럼 UNIONDISTINCT 키워드를 따로 명시하지 않아도 기본적으로 중복되는 레코드를 제거합니다.

 

따라서 이렇게 중복되는 레코드까지 모두 출력하고 싶다면, ALL 키워드를 사용해야 합니다.

 

문법

SELECT 필드이름

 

FROM 테이블이름

 

UNION ALL

 

SELECT 필드이름

 

FROM 테이블이름

 

 

 

다음 예제는 두 SELECT 문의 결과를 UNION ALL을 이용하여 하나의 테이블로 출력하는 예제입니다.

 

예제

SELECT Name

 

FROM Reservation

 

UNION ALL

 

SELECT Name

 

FROM Customer;

위의 예제에서 두 SELECT 문의 결과는 하나로 합쳐져서 출력됩니다.

 

이때 두 SELECT 문의 결과는 중복된 레코드까지 모두 표시합니다.

 

서브쿼리(subquery)

서브쿼리(subquery)란 다른 쿼리 내부에 포함되어 있는 SELETE 문을 의미합니다.

 

서브쿼리를 포함하고 있는 쿼리를 외부쿼리(outer query)라고 부르며, 서브쿼리는 내부쿼리(inner query)라고도 부릅니다.

 

서브쿼리는 반드시 괄호(())로 감싸져 있어야만 합니다.

 

 

 

MySQL에서 서브쿼리를 포함할 수 있는 외부쿼리는 SELECT, INSERT, UPDATE, DELETE, SET, DO 문이 있습니다.

 

이러한 서브쿼리는 또 다시 다른 서브쿼리 안에 포함될 수 있습니다.

 

 

 

다음 예제는 주소가 서울인 고객이 예약한 예약 정보만을 선택하는 예제입니다.

 

예제

SELECT ID, ReserveDate, RoomNum

 

FROM Reservation

 

WHERE Name IN (SELECT Name

 

FROM Customer

 

WHERE Address = '서울')

위의 예제에서 번 라인의 SELECT 문은 외부쿼리이며, 번 라인의 SELECT 문은 서브쿼리입니다.

 

 

 

우선 번 라인의 서브쿼리가 먼저 실행되어 Customer 테이블의 Address 필드의 값이 '서울'인 레코드의 Name 필드를 모두 선택합니다.

 

그리고서 번 라인의 외부쿼리가 실행되어 Reservation 테이블에서 서브쿼리에 의해 선택된 결과 집합에 포함된 Name 필드와 일치하는 레코드만을 다시 선택합니다.

 

서브쿼리의 특징

서브쿼리를 사용하면 다음과 같은 장점을 얻을 수 있습니다.

 

 

 

1. 서브쿼리는 쿼리를 구조화시키므로, 쿼리의 각 부분을 명확히 구분할 수 있게 해줍니다.

 

2. 서브쿼리는 복잡한 JOIN이나 UNION과 같은 동작을 수행할 수 있는 또 다른 방법을 제공합니다.

 

3. 서브쿼리는 복잡한 JOIN이나 UNION 보다 좀 더 읽기 편합니다.

 

 

 

다음 예제는 위에서 살펴본 주소가 서울인 고객이 예약한 예약 정보만을 선택하는 예제를 JOIN을 사용하여 표현한 것입니다.

 

쿼리가 복잡한 경우에는 JOIN이나 UNION을 사용하는 것보다 서브쿼리를 사용하는 것이 가독성 측면에서 좋을 수 있습니다.

 

예제

SELECT r.ID, r.ReserveDate, r.RoomNum

 

FROM Reservation AS r, Customer AS c

 

WHERE c.Address = '서울' AND r.Name = c.Name;

 

 

 

하지만 서브쿼리에서 사용된 테이블이나 그 결과 집합은 수정할 수 없습니다.

 

잘못된 예제

UPDATE Reservation ...

 

WHERE ReverseDate = (SELECT ... FROM Reservation ...);

 

FROM 절의 서브쿼리

서브쿼리는 SELECT 문의 FROM 절에서도 사용할 수 있습니다.

 

이때 서브쿼리에 의해 선택된 결과 집합은 FROM 절에서 하나의 테이블로써 사용됩니다.

 

문법

SELECT ...

 

FROM (서브쿼리) [AS] 이름

 

...

 

 

 

SELECT 문의 FROM 절에서 사용되는 모든 테이블에는 이름이 필요합니다.

 

따라서 FROM 절에서 사용되는 서브쿼리는 위의 문법처럼 반드시 이름을 정의해야 합니다.

 

 

 

예제

SELECT Name, ReservedRoom

 

FROM (SELECT Name, ReserveDate, (RoomNum + 1) AS ReservedRoom

 

FROM Reservation

 

WHERE RoomNum > 1001) AS ReservationInfo;

 

위의 예제는 우선 번 라인의 서브쿼리가 먼저 실행됩니다.

 

해당 서브쿼리는 Reservation 테이블에서 RoomNum 필드의 값이 1001 이상인 레코드를 찾은 후에, RoomNum 필드값을 1씩 증가시킵니다.

 

그리고 해당 결과 집합은 번 라인에서 ReservationInfo라는 이름의 임시 테이블로 만들어집니다.

 

외부쿼리에서는 이렇게 만들어진 임시 테이블에서 Name, ReservedRoom 필드만을 선택하게 됩니다.

'MySQL' 카테고리의 다른 글

MySQL 뷰  (0) 2020.07.03
MySQL 인덱스  (0) 2020.07.02
MySQL 제약조건  (0) 2020.07.02
MySQL 연산자  (0) 2020.07.02
MySQL 타입  (0) 2020.07.02

댓글