DB/postgresql

postgresql) 서브쿼리란?

STUFIT 2025. 3. 3. 23:16
반응형

데이터베이스를 다루다 보면 특정 조건을 만족하는 데이터를 추출하기 위해 **서브쿼리(Subquery)**를 사용해야 할 때가 많습니다. 서브쿼리는 다른 쿼리 안에서 실행되는 쿼리로, 종종 메인 쿼리의 조건을 결정하는 데 사용됩니다.

이번 글에서는 PostgreSQL에서 서브쿼리를 사용하는 방법실제 예제를 통해 서브쿼리를 이해해보겠습니다.

1. 서브쿼리란?

서브쿼리는 SELECT, INSERT, UPDATE, DELETE 등의 SQL 문 내부에서 실행되는 쿼리입니다. 보통 WHERE, FROM, SELECT 절에서 사용됩니다.

서브쿼리는 다음과 같이 분류할 수 있습니다:

  • 스칼라 서브쿼리 (Scalar Subquery): 하나의 값을 반환하는 서브쿼리
  • 다중 행 서브쿼리 (Multi-row Subquery): 여러 행을 반환하는 서브쿼리
  • 다중 열 서브쿼리 (Multi-column Subquery): 여러 열을 반환하는 서브쿼리
  • 상관 서브쿼리 (Correlated Subquery): 메인 쿼리의 각 행과 연관된 서브쿼리

2. 서브쿼리 예제 데이터 준비

서브쿼리를 이해하기 쉽게 간단한 테이블을 만들어 보겠습니다.

-- 고객 테이블
CREATE TABLE customers (
    id SERIAL PRIMARY KEY,
    name VARCHAR(50),
    city VARCHAR(50)
);

-- 주문 테이블
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(id),
    amount DECIMAL(10,2),
    order_date DATE
);

-- 샘플 데이터 삽입
INSERT INTO customers (name, city) VALUES
('Alice', 'Seoul'),
('Bob', 'Busan'),
('Charlie', 'Incheon');

INSERT INTO orders (customer_id, amount, order_date) VALUES
(1, 150.50, '2024-02-20'),
(1, 200.75, '2024-02-22'),
(2, 99.99, '2024-02-21'),
(3, 300.00, '2024-02-23');

3. 서브쿼리 활용 예제

(1) WHERE 절에서 서브쿼리 사용

특정 고객의 주문이 존재하는지 확인하기

SELECT name FROM customers
WHERE id IN (SELECT customer_id FROM orders);

💡 이 쿼리는 orders 테이블에 주문 기록이 있는 고객만 조회합니다.

(2) SELECT 절에서 서브쿼리 사용 (스칼라 서브쿼리)

각 고객의 총 주문 금액을 함께 조회하기

SELECT name,
       (SELECT COALESCE(SUM(amount), 0) FROM orders WHERE orders.customer_id = customers.id) AS total_spent
FROM customers;

💡 COALESCE 함수를 사용하여 주문이 없는 고객은 0을 반환하도록 설정했습니다.

(3) FROM 절에서 서브쿼리 사용 (인라인 뷰)

고객별 총 주문 금액을 별도의 서브쿼리로 계산하기

SELECT c.name, o.total_spent
FROM customers c
JOIN (SELECT customer_id, SUM(amount) AS total_spent FROM orders GROUP BY customer_id) o
ON c.id = o.customer_id;

💡 FROM 절에 서브쿼리를 사용하면, **가상의 테이블(인라인 뷰)**을 만들 수 있습니다.

(4) 상관 서브쿼리 (Correlated Subquery)

가장 최근 주문 금액 조회하기

SELECT name,
       (SELECT amount FROM orders o WHERE o.customer_id = c.id ORDER BY order_date DESC LIMIT 1) AS latest_order
FROM customers c;

💡 각 고객의 마지막 주문 금액을 조회하는 서브쿼리입니다. 상관 서브쿼리는 메인 쿼리의 각 행을 기준으로 실행됩니다.


4. 서브쿼리 vs JOIN 성능 비교

서브쿼리는 간단하지만 경우에 따라 JOIN이 더 성능이 좋을 수 있습니다. 특히, 다중 행을 반환하는 서브쿼리는 JOIN으로 변경하는 것이 일반적으로 효율적입니다.

예를 들어, 아래 두 개의 쿼리는 같은 결과를 반환하지만, JOIN 방식이 더 성능이 좋을 가능성이 큽니다.

서브쿼리 방식

SELECT name,
       (SELECT SUM(amount) FROM orders WHERE orders.customer_id = customers.id) AS total_spent
FROM customers;

JOIN 방식 (더 효율적)

SELECT c.name, COALESCE(SUM(o.amount), 0) AS total_spent
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
GROUP BY c.id;

💡 LEFT JOIN을 사용하면 주문이 없는 고객도 포함할 수 있습니다.


5. 정리

  • 서브쿼리는 쿼리 내부에서 실행되는 또 다른 쿼리입니다.
  • WHERE, SELECT, FROM 절 등 다양한 곳에서 사용됩니다.
  • 상관 서브쿼리는 메인 쿼리의 각 행과 연관되어 실행됩니다.
  • 성능을 고려할 때 서브쿼리보다 JOIN이 더 나은 선택일 수도 있습니다.

PostgreSQL을 다루면서 서브쿼리를 활용하면 더 복잡한 데이터를 효과적으로 처리할 수 있습니다. 하지만 성능을 항상 고려하여 JOIN이나 인덱스를 적절히 활용하는 것이 중요합니다.

 

반응형