대부분의 쿼리는 2개 이상의 테이블이 필요한 경우가 많을거다.
1개 테이블에 모든 정보를 다 넣을수가 없기 때문이다.
이 경우, FOREIGN KEY
를 연결수단으로 사용하여 2개 이상의 테이블의 열을 하나의 결과셋에 보여지게 할 수 있다.
이걸 조인 JOIN
이라고 한다.
FROM
절에 JOIN
을 사용하여 두개의 테이블을 연결하는 방법으로 교차 조인 이라고 하지만 거의 사용하지 않는다.
예를 들어, 고객의 성, 이름, 주소를 한번에 보고 싶다고 하자.
데카르트 곱(교차조인) 사용 :
SELECT customer.first_name, customer.last_name, address.address
FROM customer
JOIN address;
----------
361197 rows in set
교차 조인을 사용하면 고객 599명 * 주소 603개 = 361,197개의 조합을 생성하여 행으로 반환한다. 쿼리가 어떻게 두 테이블을 조인해야할지 몰라서 데카르트 곱으로 합쳤기 때문이다.
customer 테이블과 address 테이블을 살펴보자.
address_id
를 이용하여 2개의 테이블을 조인해보자.
/*(방법1) FROM 절의 하위절에 JOIN ... ON 을 추가*/
SELECT c.first_name, c.last_name, a.address
FROM customer c
JOIN address a
ON c.address_id = a.address_id ;
/*(방법2) INNER JOIN ... ON 사용 => 추천! */
SELECT c.first_name, c.last_name, a.address
FROM customer c
INNER JOIN address a
ON c.address_id = a.address_id ;
/*(방법3) 두 테이블을 조인할 때, 열의 이름이 동일한 경우(address_id처럼)
-> ON 대신 USING 사용 가능*/
SELECT c.first_name, c.last_name, a.address
FROM customer c
INNER JOIN address a
USING (address_id);
이 책에서 테이블 조인에 사용된 문법은 ANSI SQL 표준의 SQL92 버전이다.
조인과 필터조건을 동시에 포함하는 쿼리를 살펴보자.
SELECT c.first_name, c.last_name, a.address
FROM customer c
INNER JOIN address a
ON c.address_id = a.address_id
WHERE a.postal_code = 52137 ;
----------
2 rows in set
customer 테이블과 address 테이블을 합친뒤(조인), 우편번호가 52137인 고객만(필터) 결과셋에 나타난다.
3개 테이블을 조인할 때는 FROM
절에 3개의 테이블과 2개의 조인유형이 있고, 2개의 ON
하위절이 있게된다.
이번에는 고객의 주소가 아니라 '도시'를 반환해보자.
address_id
를 사용해 customer 테이블과 address 테이블을 연결하고, city_id
를 통해 address 테이블과 city 테이블을 연결해야한다.
SELECT c.first_name, c.last_name, ct.city
FROM customer c
INNER JOIN address a
ON c.address_id = a.address_id
INNER JOIN city ct
ON a.city_id = ct.city_id ;
이때 FROM
절에서 테이블을 쓰는 순서는 중요하지 않다. (city 테이블을 먼저 써도 같은 결과)
왜냐하면 SQL은 비절차적 언어로, 데이터베이스 서버가 알아서 쿼리를 잘 실행하는 방법을 결정하기 때문이다.
서브쿼리를 사용해 address 테이블에서 district
가 캘리포니아인 고객들의 성, 이름, 주소, 도시를 가져와보자.
SELECT
c.first_name
, c.last_name
, addr.address
, addr.city
, addr.district
FROM customer c
INNER JOIN
(SELECT
a.address_id
, a.address
, ct.city
, a.district
FROM address a
INNER JOIN city ct
ON a.city_id = ct.city_id
WHERE a.district = 'California'
) addr
ON c.address_id = addr.address_id ;
film, film_actor, actor 3개의 테이블을 이용하여 2명의 특정 배우가 출연한 영화 제목을 모두 찾아보자.
SELECT
f.title
, a.first_name
, a.last_name
FROM film f
INNER JOIN film_actor fa
ON f.film_id = fa.film_id
INNER JOIN actor a
ON fa.actor_id = a.actor_id
WHERE
(
(a.first_name = 'CATE' AND a.last_name = 'MCQUEEN')
OR (a.first_name = 'CUBA' AND a.last_name = 'BIRCH')
) ;
----------
54 rows in set
만약, Cate Mcqueen 과 Cuba Birch 가 모두 출연한 영화만 검색하고 싶다면 배우 각각을 검색할 수 있도록 쿼리를 짜야한다.
SELECT
f.title
FROM film f
INNER JOIN film_actor fa1
ON f.film_id = fa1.film_id
INNER JOIN actor a1
ON fa1.actor_id = a1.actor_id
INNER JOIN film_actor fa2
ON f.film_id = fa2.film_id
INNER JOIN actor a2
ON fa2.actor_id = a2.actor_id
WHERE
(a1.first_name = 'CATE' AND a1.last_name = 'MCQUEEN')
AND (a2.first_name = 'CUBA' AND a2.last_name = 'BIRCH');
----------
2 rows in set
Blood Argonauts와 Towers Hurricane 2개의 영화제목만 보여진다.
책에서의 설명만으로 셀프조인을 이해하기가 어려워서 2개의 블로그를 정독했다 😓 (나는 멍청이...)
어쨌든 내가 이해한 내용은 이렇다.
보통 조인이라고 하면 2개의 테이블을 PK, FK를 사용해 합치는데, 셀프조인은 1개의 테이블에서 자기 자신의 PK값을 사용해 합치는거다.
음.....🤔
보통 JOIN
을 할 때는 [테이블1] INNER JOIN [테이블2] ON [조인 조건]
이 들어가게되는데, 셀프조인은 이 테이블 1,2가 같은 테이블인거다.
따라서 같은 테이블이 2번 쿼리에 등장하므로 반드시 alias(별칭)을 지정하자.