[ 살펴보기 ] Sql - 서브쿼리
![[ 살펴보기 ] Sql - 서브쿼리](https://cdn.hashnode.com/res/hashnode/image/upload/v1720753448010/3dc825a7-6618-410d-a270-199bcf5791db.jpeg)
서브쿼리는 다른 쿼리 구문에 포함되는 쿼리구문을 말한다. 괄호 안에 서브쿼리를 작성하여 서브쿼리를 포함하고 있는 포함 쿼리 보다 먼저 실행되고 그 결과를 포함쿼리에서 사용할 수 있다.
다음 예제를 살펴보자
SELECT actor_id, film_id
FROM film_actor
WHERE film_id IN (SELECT film_id FROM film WHERE rating = "PG")
위의 예제에서 서브쿼리는 (SELECT film_id FROM film WHERE rating = "PG") 부분이다. 서브쿼리가 반환한 데이터가 포함 구문이 필요한 조회를 할 때 사용되는 것이다.
위의 예제는 film 이라는 table에서 rating이 PG인 영화의 id를 찾고 그 결과를 기준으로 film_actor라는 table에서 해당 film_id 데이터를 가진 actor id를 찾는다.
서브쿼리에는 포함 구문과 독립적으로 처리되는 비상관 서브쿼리와 포함 구문의 결과 값을 참조하는 상관 서브쿼리로 나뉜다. 먼저 비상관 서브쿼리부터 살펴보자
비상관 서브쿼리
포함쿼리의 결과를 참조하지 않고 개별적으로 실행되는 서브쿼리를 말한다. 위에서 살펴봤던 서브쿼리는 포함쿼리의 결과를 참조하지 않고 개별적으로 실행되므로 비상관 서브쿼리다. 또 다른 예제를 한번 살펴보자
SELECT rental_id, customer_id, rental_date, return_date,
FROM rental
WHERE customer_id
IN (SELECT customer_id FROM customer WHERE first_name LIKE "J%")
위의 예제에선 (SELECT customer_id FROM customer WHERE first_name LIKE "J%") 서브쿼리를 통해 first_name이 J로 시작하는 customer를 기준으로 필요한 데이터를 포함쿼리에서 조회하고 있다.
서브쿼리에서도 JOIN과 같은 다소 복잡한 쿼리를 수행할 수도 있다. 다음은 서브쿼리를 이용해 영화 제목이 BA로 시작하는 영화에 출연했던 배우의 정보를 조회하는 쿼리의 예제이다
SELECT actor_id, first_name
FROM actor
WHERE actor_id IN
(
SELECT film_actor.actor_id FROM film_actor
INNER JOIN film
ON film_actor.film_id = film.film_id
WHERE film.title LIKE 'BA%'
)
ORDER BY actor.actor_id
상관 서브쿼리
위에서 살펴본 서브쿼리 예제들은 비상관 서브쿼리로서 포함 구문의 결과를 조회하지 않고 서브쿼리로 부터 독립적인 쿼리였다면 상관 서브쿼리는 포함 구문의 결과를 참조하고 포함 구문의 결과에 의존하여 서브쿼리가 수행된다.
다음 예제를 살펴보자
SELECT actor_id, first_name
FROM actor
WHERE first_name IN
(
SELECT first_name FROM customer
WHERE actor.first_name = customer.first_name
)
ORDER BY actor.first_name
위의 예제에서는 서브쿼리에서 조건 필터를 위해 포함 쿼리인 actor table에 의존하고 있다. 주의할 점은 상관 쿼리를 사용하면 포함쿼리의 모든 행에 실행되므로 포함쿼리가 반환하는 행의 숫자가 크면 성능문제가 발생할 수 있으니 주의가 필요하다
상관 서브쿼리는 update나 delete와 같이 쿼리문에 유용하게 사용될 수 있다. 실용적인 예는 아니지만 예를 들어 위의 예제처럼 customer table에 같은 first_name이 존재하는 actor 테이블의 city column을 일괄적으로 변경하고 싶다면 다음과 같이 처리할 수 있을 것 이다
UPDATE actor
SET city = "new town"
WHERE first_name IN
(
SELECT first_name FROM customer
WHERE actor.first_name = customer.first_name
)
서브쿼리의 결과를 데이터 소스로 사용
위의 예제에서 살펴보았듯이 서브쿼리의 결과를 데이터 소스로서 사용할 수 있다. 다음의 예제와 같이 JOIN절의 대상으로도 활용 가능하다
SELECT customer.customer_id, customer.first_name FROM customer
INNER JOIN
(
SELECT first_name FROM actor WHERE first_name LIKE "A%"
) AS actorRecord
ON customer.first_name = actorRecord.first_name
위의 예제는 서브쿼리의 결과는 JOIN의 대상으로 활용하는 예이다. 서브쿼리에서 first_name이 A로 시작하는 actor를 찾고 그 결과를 기반으로 포함쿼리에서 같은 first_name을 가진 데이터를 조회한다
![[ 살펴보기 ] RDB - Relationships](https://cdn.hashnode.com/res/hashnode/image/upload/v1739711556668/48dc9e84-a621-42aa-9c9f-5fc5c436f0ec.jpeg)
![[ 살펴보기 ] MySQL - Data types](https://cdn.hashnode.com/res/hashnode/image/upload/v1739593589113/530f8704-4d27-42c9-a451-bb5c63150b99.jpeg)
![[ 살펴보기 ] TypeORM - Transactions, Migration](https://cdn.hashnode.com/res/hashnode/image/upload/v1739106042581/980b8133-61d4-406a-a026-65be9c28eace.jpeg)
![[ 살펴보기 ] TypeORM - Relations](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666874402/b688bd0b-b6bb-4f43-87d8-c1b46b59f1b7.jpeg)
![[ 살펴보기 ] TypeORM - Basics](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666803591/bef5df17-7dc7-4123-ae55-004d5042df39.jpeg)