서브쿼리는 SQL 문 안에 다른 SQL 문을 포함하여 사용하는 쿼리입니다. 하나의 SQL 문에서 필요한 데이터를 먼저 조회한 다음 그 결과를 바깥쪽 쿼리에서 다시 활용할 수 있습니다. 특정 조건에 맞는 데이터를 먼저 찾고 그 결과를 기준으로 다른 데이터를 조회해야 하는 상황에서 주로 사용합니다.

서브쿼리의 기본 개념

일반적인 SQL은 하나의 SELECT 문을 이용하여 필요한 데이터를 조회합니다.

SELECT name, price
FROM product
WHERE price >= 50000;

하지만 어떤 값을 직접 알고 있지 않고 데이터베이스에서 먼저 조회해야 하는 경우가 있습니다.

예를 들어 상품의 평균 가격보다 비싼 상품을 조회한다고 가정하겠습니다. 평균 가격을 직접 입력할 수 있다면 간단하지만, 평균 가격은 상품 데이터가 변경될 때마다 달라질 수 있습니다.

이때 서브쿼리를 사용할 수 있습니다.

SELECT name, price
FROM product
WHERE price > (
    SELECT AVG(price)
    FROM product
);

괄호 안에 있는 SELECT 문이 서브쿼리입니다.

먼저 안쪽의 서브쿼리가 상품의 평균 가격을 계산합니다.

SELECT AVG(price)
FROM product;

예를 들어 평균 가격이 50,000원이라는 결과가 나오면 바깥쪽 쿼리는 다음과 같은 조건으로 데이터를 조회하는 것과 비슷한 형태가 됩니다.

SELECT name, price
FROM product
WHERE price > 50000;

즉, 서브쿼리는 다른 쿼리의 결과를 현재 쿼리에서 사용하기 위한 방법이라고 이해할 수 있습니다.

WHERE에서 사용하는 서브쿼리

서브쿼리는 WHERE 절에서 자주 사용됩니다. 특히 특정 값을 직접 입력하지 않고 다른 데이터를 조회한 결과를 조건으로 사용해야 할 때 유용합니다.

예를 들어 가장 비싼 상품의 가격을 먼저 구한 뒤 해당 가격을 가진 상품을 조회할 수 있습니다.

SELECT name, price
FROM product
WHERE price = (
    SELECT MAX(price)
    FROM product
);

안쪽의 서브쿼리는 상품 가격 중 가장 큰 값을 찾습니다.

SELECT MAX(price)
FROM product;

이 결과를 바깥쪽 쿼리의 WHERE 조건에서 사용하여 가장 비싼 상품을 조회합니다.

서브쿼리는 다른 테이블의 데이터를 조건으로 사용할 때도 활용할 수 있습니다.

예를 들어 주문을 한 적이 있는 회원의 정보만 조회한다고 가정하겠습니다.

SELECT name
FROM member
WHERE id IN (
    SELECT member_id
    FROM orders
);

서브쿼리는 orders 테이블에서 주문한 회원의 ID를 먼저 조회합니다. 바깥쪽 쿼리는 그 결과에 포함된 회원 ID를 가진 회원을 조회합니다.

여기에서는 여러 개의 값이 반환될 수 있기 때문에 IN을 사용합니다.

반면 서브쿼리가 하나의 값만 반환하는 경우에는 =이나 >, < 등의 비교 연산자를 사용할 수 있습니다.

SELECT name, price
FROM product
WHERE price > (
    SELECT AVG(price)
    FROM product
);

AVG()는 하나의 평균값을 반환하므로 > 연산자를 사용할 수 있습니다.

FROM과 SELECT에서 사용하는 서브쿼리

서브쿼리는 WHERE뿐만 아니라 FROM에서도 사용할 수 있습니다. FROM에서 사용하는 서브쿼리는 먼저 조회 결과를 하나의 임시 테이블처럼 만든 다음 바깥쪽 쿼리에서 다시 사용할 수 있습니다.

예를 들어 상품별 평균 가격을 먼저 계산하고 그 결과를 다시 조회한다고 가정하겠습니다.

SELECT category, average_price
FROM (
    SELECT category, AVG(price) AS average_price
    FROM product
    GROUP BY category
) AS category_price;

괄호 안쪽의 쿼리가 먼저 상품을 카테고리별로 그룹화하고 평균 가격을 계산합니다.

그 결과를 category_price라는 별칭으로 지정하고 바깥쪽 SELECT에서 다시 조회합니다.

FROM 절에 서브쿼리를 사용할 때는 일반적으로 서브쿼리에 별칭을 지정해야 합니다.

FROM (
    SELECT category, AVG(price) AS average_price
    FROM product
    GROUP BY category
) AS category_price

이 방식은 복잡한 데이터를 먼저 가공한 다음 그 결과를 다시 조회해야 하는 경우에 유용합니다.

SELECT 절에서도 서브쿼리를 사용할 수 있습니다. 예를 들어 상품 목록과 함께 전체 상품의 평균 가격을 표시할 수도 있습니다.

SELECT name,
       price,
       (SELECT AVG(price) FROM product) AS average_price
FROM product;

이 경우 각각의 상품 가격과 함께 전체 상품의 평균 가격이 조회 결과에 표시됩니다.

다만 서브쿼리를 사용한다고 항상 더 좋은 SQL이 되는 것은 아닙니다. 같은 결과를 JOIN이나 다른 SQL 구조로 표현할 수 있는 경우도 있기 때문에 데이터의 양과 쿼리 구조를 고려해야 합니다.

특히 서브쿼리가 복잡해질수록 SQL을 이해하고 수정하기 어려워질 수 있습니다. 따라서 서브쿼리는 필요한 상황에서 적절하게 사용하는 것이 중요합니다.

서브쿼리에는 하나의 값만 반환하는 단일 행 서브쿼리와 여러 개의 값을 반환하는 다중 행 서브쿼리 등이 있으며, 상황에 따라 =, IN, EXISTS 등의 연산자를 사용할 수 있습니다.

또한 서브쿼리와 JOIN은 서로 완전히 같은 기능은 아닙니다. JOIN은 여러 테이블의 관련 데이터를 연결하여 조회하는 데 중점을 두고, 서브쿼리는 다른 쿼리의 결과를 현재 쿼리의 조건이나 데이터로 활용하는 데 중점을 둡니다. 실제 SQL에서는 두 방식을 함께 사용하는 경우도 있습니다.

결국 서브쿼리는 하나의 SQL 문 안에 다른 SQL 문을 포함하여 그 결과를 바깥쪽 쿼리에서 활용하는 방법입니다. WHERE에서는 다른 쿼리의 결과를 조건으로 사용할 수 있고, FROM에서는 서브쿼리의 결과를 하나의 임시 데이터 집합처럼 활용할 수 있습니다. 데이터베이스에서 복잡한 조건을 처리하거나 여러 단계의 조회가 필요한 경우 유용하게 사용할 수 있으며, 이후 배우게 될 인덱스와 함께 SQL 성능을 고려하면서 사용하는 것도 중요합니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

글쓴이

rjsan46@koreabites.com

관련 게시물

복합 인덱스란 무엇인가

복합 인덱스는 데이터베이스에서 두 개 이상의 컬럼을 하나의 인덱스로 묶어 사용하는 방식입니다. 하나의 컬럼만 검색하는 단일 인덱스와 달리 여러 컬럼을 함께 조건으로...

모두 읽어보기

인덱스가 빠른 이유

인덱스가 빠른 이유는 데이터베이스가 검색할 때 테이블의 모든 데이터를 처음부터 끝까지 확인하지 않고, 별도로 구성된 검색 구조를 이용하여 필요한 데이터의 위치를 빠르게...

모두 읽어보기

인덱스란 무엇인가

인덱스는 데이터베이스에서 원하는 데이터를 빠르게 찾기 위해 사용하는 자료 구조입니다. 데이터가 많아질수록 모든 데이터를 하나씩 확인하는 방식은 검색 시간이 증가하기 때문에 인덱스를...

모두 읽어보기

INNER JOIN과 OUTER JOIN 차이

INNER JOIN과 OUTER JOIN은 서로 다른 테이블의 데이터를 연결할 때 어떤 데이터를 조회 결과에 포함할 것인지 결정하는 JOIN 방식입니다. INNER JOIN은 두...

모두 읽어보기

JOIN이란 무엇인가

JOIN은 SQL에서 서로 다른 테이블에 저장된 데이터를 연결하여 하나의 조회 결과로 가져올 때 사용하는 구문입니다. 관계형 데이터베이스에서는 하나의 테이블에 모든 데이터를 저장하기보다...

모두 읽어보기

DELETE란 무엇인가

DELETE는 SQL에서 테이블에 저장된 기존 데이터를 삭제할 때 사용하는 구문입니다. INSERT가 새로운 데이터를 추가하고 UPDATE가 기존 데이터를 수정한다면 DELETE는 더 이상 필요하지...

모두 읽어보기