Learning SQL 5장 요약 - 다중 테이블 쿼리

SQL

2022. 11. 24. 18:41


5장 다중 테이블 쿼리

 

5장에서는 inner join을 중점으로 살펴본다. (outer join은 10장에서)

 

customer 테이블의 address_id는

address 테이블의 외래 키이다.

 

조인

 

데카르트 곱(카테시안 곱)

가장 원시적인 join방식이다.

N행의 테이블과 M행의 테이블을 join하면 N*M행 개의 데이터를 불러온다.

SELECT c.first_name, c.last_name, a.address
FROM customer c JOIN address a;

(위 쿼리를 실행하지는 말자...

고객 이름별로 모든 주소가 매칭되어서 데이터를 불러온다.)

 

내부조인

각 고객에 대해 단일 행(주소)만 반환하도록 하려면

from 절 하위에 on 하위절로 조건을 추가하자.

SELECT c.first_name, c.last_name, a.address
FROM customer c JOIN address a
ON c.address_id = a.address_id;

 

내부조인을 사용할 땐 inner임을 명시해야 한다.

SELECT c.first_name, c.last_name, a.address
FROM customer c INNER JOIN address a
ON c.address_id = a.address_id;

 

위 예제처럼 열의 이름이 동일할 경우 on 하위절 대신 using 절을 사용할 수 있다.

SELECT c.first_name, c.last_name, a.address
FROM customer c JOIN address a
USING(address_id);

 

ANSI 조인 문법 (SQL92버전)

SELECT c.first_name, c.last_name, a.address
FROM customer c, address a
WHERE c.address_id = a.address_id
  AND a.postal_code = 52137;

 

그러나 where절의 어떤 조건이 조인조건이고 어떤조건이 필터조건인지 알기 어렵다.

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;

 

세 개 이상 테이블 조인

고객의 주소가 아닌 도시를 반환하는 예시

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;

SQL은 비절차적 언어라서 테이블 순서에 따라 결과가 달라지진 않는다.

 

서브쿼리 사용

SELECT c.first_name, c.last_name, addr.address, addr.city
FROM customer c
	INNER JOIN (
    	SELECT a.address_id, a.address, ct.city
        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를 desc로 확인해보자)

 

두 명의 특정 배우가 출연한 영화를 film 테이블에서 검색하는 예시

SELECT f.title
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'));

 

두 명의 특정 배우가 모두 출연한 영화를 film 테이블에서 검색하는 예시

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');

 

셀프 조인

영화 제목과 영화 프리퀄의 제목을 검색하는 예시

(※ prequel_film_id가 있다는 가정 하의 예시다.

실제 이런 컬럼은 없다.)

SELECT f.title, f_prnt.title prequel
FROM film f
    INNER JOIN film f_prnt
    ON f_prnt.film_id = f.prequel_film_id

WHERE f.prequel_film_id IS NOT NULL;