Skip to main content

Command Palette

Search for a command to run...

[ 살펴보기 ] Sql - 서브쿼리

Updated
2 min readView as Markdown
[ 살펴보기 ] Sql - 서브쿼리
C

A developer living in Busan, Korea

서브쿼리는 다른 쿼리 구문에 포함되는 쿼리구문을 말한다. 괄호 안에 서브쿼리를 작성하여 서브쿼리를 포함하고 있는 포함 쿼리 보다 먼저 실행되고 그 결과를 포함쿼리에서 사용할 수 있다.

다음 예제를 살펴보자

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을 가진 데이터를 조회한다

More from this blog

[ 살펴보기 ] TypeORM - Transactions, Migration

Transation Database 종류에 따라 detail한 부분은 차이점이 조금씩 있겠지만 각 sql statement는 개별적인 transaction block을 통해 실행되며 Database 설정에 따라 sql statement의 실행 결과가 자동으로 commit되어 영구히 적용되거나 commit을 직접 실행하기 전까지는 영구히 적용되지 않을 수 있다. 대부분의 경우 default로 sql statement 실행 결과가 자동으로 comm...

Feb 9, 20256 min read
[ 살펴보기 ] TypeORM - Transactions, Migration

Dev Diary

184 posts