SQL: Sub Query

김기현·2025년 6월 15일

Database

목록 보기
14/24

서브쿼리는 SQL에서 쿼리 안에 다른 쿼리를 사용하는 것을 말한다. 일반적으로 소괄호 안에 작성되고 메인 쿼리 또는 외부 쿼리에서 그 결과를 사용한다.

개념

SELECT, FROM, WHERE, HAVING, JOIN절 등에 포함될 수 있는 중첩된 쿼리이다. 이 쿼리는 메인 쿼리에 값을 제공하거나 조건을 설정하는데 사용된다.

서브 쿼리 종류

테이블 스키마는 아래와 같다.

CREATE TABLE employee
(
    employee_id   INT PRIMARY KEY AUTO_INCREMENT,
    name          VARCHAR(100)   NOT NULL,
    salary        DECIMAL(15, 2) NOT NULL,
    department_id INT,
    FOREIGN KEY (department_id) REFERENCES department (department_id)
);

CREATE TABLE department
(
    department_id INT PRIMARY KEY AUTO_INCREMENT,
    name          VARCHAR(100) NOT NULL,
    location      VARCHAR(100)
);

스칼라 서브쿼리

하나의 값을 반환한다.

SELECT name
FROM employee
WHERE department_id = (SELECT department_id
                       FROM department
                       WHERE name = 'HR');

인라인 뷰

FROM 절에 들어가 테이블처럼 사용된다.

SELECT avg_salary.department_id, avg_salary.avg
FROM (SELECT department_id, AVG(salary) AS avg
      FROM employee
      GROUP BY department_id) AS avg_salary;

다중 행 서브쿼리

여러 행을 반환하며, IN, ANY, ALL과 함께 사용된다.

SELECT name
FROM employee
WHERE department_id IN (SELECT department_id
                        FROM department
                        WHERE location = 'Seoul');

상관 서브쿼리

서브쿼리가 메인 쿼리의 값을 참조한다. 메인 쿼리의 각 행마다 서브쿼리가 실행된다.

SELECT name
FROM employee e
WHERE salary > (SELECT AVG(salary)
                FROM employee
                WHERE department_id = e.department_id);

서브쿼리 실행 시점과 결과 활용

  • 서브쿼리는 메인 쿼리 실행 전에 먼저 실행되어 결과가 반환된다.
  • 메인 쿼리는 이 결과를 사용해서 최종 데이터를 추출한다.
  • 상관 서브쿼리는 메인 쿼리의 각 행마다 실행되어 성능에 영향을 줄 수 있다.

서브쿼리와 인덱스 활용

  • 서브쿼리에 적절한 인덱스가 없으면 성능 저하가 심하다.
  • 특히 서브쿼리의 결과가 큰 경우, 인덱스를 통한 필터링 여부가 중요하다.

서브쿼리의 사용 제한

  • 일부 DBMS에서는 FROM절에 서브쿼리를 제한하거나, 특정 서브쿼리 형태를 지원하지 않는 경우가 있다.
  • 따라서 사용하는 DBMS에 따라서 다르게 사용해야 한다.

서브쿼리 대체 가능성

서브쿼리는 가끔 JOIN, Common Table Expressions, 윈도우 함수 등으로 대체 가능하며, 이 경우 성능과 가독성이 개선될 수 있다.

-- 원본 SQL
SELECT e.name, a.avg
FROM employee e
         JOIN (SELECT department_id, AVG(salary) AS avg
               FROM employee
               GROUP BY department_id) a ON e.department_id = a.department_id;


-- 서브쿼리가 대체된 SQL
WITH avg_salary AS (SELECT department_id, AVG(salary) AS avg
                    FROM employee
                    GROUP BY department_id)
SELECT e.name, a.avg
FROM employee e
         JOIN avg_salary a ON e.department_id = a.department_id;
  • CTE 대신에 FROM절 안에 서브쿼리를 직접 넣어서 avg_salary테이블처럼 사용한 형태이다.
  • 실행 계획상 큰 차이는 없지만 일부 DBMS에서는 CTE를 최적화하지 않고 따로 실행할 수 있어 성능 차이가 클 수 있다.

  • 가능하다면 상관 서브쿼리보다는 비상관 서브쿼리 또는 조인으로 변환해 성능을 개선한다.
  • 복잡한 서브쿼리는 가독성을 위해 주석과 함께 작성한다.
  • 쿼리 실행 계획(EXPLAIN PLAN)을 통해 서브쿼리 성능을 분석해야 한다.

서브쿼리와 조인

  • 서브쿼리는 중첩 구조로 복잡한 조건을 간결하게 표현할 수 있다.
  • 조인은 여러 테이블을 연결해 한 번에 데이터를 조회할 수 있어 성능상 더 유리할 수 있다.

주의사항

  • 성능: 특히 상관 서브쿼리의 경우 반복적으로 실행되므로 성능이 떨어질 수 있다.
  • 가독성: 복잡한 서브쿼리는 서브쿼리보다 조인이 더 명확할 때도 있다.
profile
백엔드 개발자를 목표로 공부하는 대학생

0개의 댓글