본문 바로가기
JPA Study

서브쿼리 (Subquery)

by xogns93 2024. 9. 23.

서브쿼리(Subquery)는 SQL에서 다른 쿼리 내에 포함된 쿼리를 말합니다. 서브쿼리는 일반적으로 내부 쿼리 또는 중첩 쿼리라고도 하며, 메인 쿼리(Main Query)에 의해 참조되어 데이터를 반환하거나 필터링하는 데 사용됩니다. 서브쿼리는 하나의 쿼리 내에서 다른 쿼리의 결과를 참조하거나 비교하기 위해 사용됩니다.

서브쿼리의 기본 구조

서브쿼리는 일반적으로 괄호 안에 작성되며, 메인 쿼리와 함께 실행됩니다.

SELECT column1, column2
FROM table_name
WHERE columnX = (SELECT column FROM another_table WHERE condition);
  • 서브쿼리: SELECT column FROM another_table WHERE condition 부분이 서브쿼리입니다.
  • 메인 쿼리: SELECT column1, column2 FROM table_name WHERE columnX = ...가 메인 쿼리입니다.

서브쿼리는 메인 쿼리의 WHERE, SELECT, FROM, 또는 HAVING 절에서 사용될 수 있습니다.

서브쿼리의 특징

  1. 내부 쿼리:
    • 서브쿼리는 항상 내부에 있는 쿼리로, 다른 쿼리의 결과를 참조하거나 계산에 사용됩니다.
  2. 단일 값 반환 또는 여러 값 반환:
    • 서브쿼리는 단일 값을 반환할 수도 있고, 여러 행의 결과를 반환할 수도 있습니다.
  3. 종속/비종속 서브쿼리:
    • 종속 서브쿼리(Correlated Subquery): 서브쿼리가 메인 쿼리의 결과에 의존하여 실행됩니다.
    • 비종속 서브쿼리(Non-correlated Subquery): 서브쿼리가 독립적으로 실행되며, 메인 쿼리와 상관없이 독립적으로 값을 반환합니다.

서브쿼리 사용 위치

 

서브쿼리는 SQL 쿼리 내에서 다양한 위치에 사용할 수 있습니다. 주로 사용되는 위치는 WHERE, FROM, SELECT, HAVING 절입니다.

1. WHERE 절에서 서브쿼리 사용

WHERE 절에서 서브쿼리는 주로 특정 조건을 만족하는지 확인하기 위해 사용됩니다.

SELECT name
FROM Employees
WHERE salary > (SELECT AVG(salary) FROM Employees);

위 쿼리는 직원들의 평균 급여보다 높은 급여를 받는 직원을 조회합니다. 서브쿼리는 평균 급여를 계산한 후, 메인 쿼리가 해당 결과를 이용해 필터링을 수행합니다.

2. FROM 절에서 서브쿼리 사용

FROM 절에서 서브쿼리를 사용하면, 서브쿼리의 결과를 임시 테이블처럼 사용할 수 있습니다.

SELECT subquery_table.name, subquery_table.salary
FROM (SELECT name, salary FROM Employees WHERE department = 'HR') subquery_table;

이 쿼리는 서브쿼리에서 HR 부서의 직원을 먼저 선택하고, 그 결과를 subquery_table로 간주하여 외부 쿼리에서 이를 참조합니다.

3. SELECT 절에서 서브쿼리 사용

SELECT 절에서 서브쿼리는 주로 동시에 다른 값을 계산하는 데 사용됩니다.

SELECT name, (SELECT AVG(salary) FROM Employees) AS avg_salary
FROM Employees;

위 쿼리는 각 직원의 이름과 전체 평균 급여를 조회합니다. 서브쿼리는 평균 급여를 계산하고, 메인 쿼리의 SELECT 절에서 그 값을 참조합니다.

4. HAVING 절에서 서브쿼리 사용

HAVING 절에서 서브쿼리는 그룹화된 데이터에 조건을 걸 때 유용합니다.

SELECT department, AVG(salary)
FROM Employees
GROUP BY department
HAVING AVG(salary) > (SELECT AVG(salary) FROM Employees);

이 쿼리는 전체 평균 급여보다 높은 부서별 평균 급여를 조회합니다. HAVING 절에서 서브쿼리를 사용해 전체 평균 급여를 비교 기준으로 사용하고 있습니다.


종속 서브쿼리와 비종속 서브쿼리

  1. 종속 서브쿼리 (Correlated Subquery):
    • 서브쿼리가 메인 쿼리의 각 행을 참조하여 실행됩니다. 즉, 서브쿼리가 메인 쿼리의 값을 기준으로 동작합니다.
    • 예시:
      SELECT name
      FROM Employees e
      WHERE salary > (SELECT AVG(salary) FROM Employees WHERE department = e.department);
      이 쿼리에서 서브쿼리는 Employees 테이블의 각 행에서 참조되는 department 값을 기준으로 실행됩니다. 즉, 각 부서별 평균 급여보다 높은 급여를 받는 직원을 조회합니다.
  2. 비종속 서브쿼리 (Non-correlated Subquery):
    • 서브쿼리가 메인 쿼리와 독립적으로 실행됩니다. 메인 쿼리와 관계없이 서브쿼리가 먼저 실행되고 그 결과를 메인 쿼리가 참조합니다.
    • 예시:
      SELECT name
      FROM Employees
      WHERE salary > (SELECT AVG(salary) FROM Employees);
      이 쿼리에서 서브쿼리는 먼저 전체 평균 급여를 계산하고, 그 결과를 메인 쿼리가 참조하여 필터링합니다.

서브쿼리의 장점과 단점

장점:

  • 복잡한 조건을 처리: 서브쿼리를 사용하면 단일 쿼리로는 처리하기 어려운 복잡한 조건을 구현할 수 있습니다.
  • 논리적 분리: 서브쿼리는 메인 쿼리에서 수행할 수 없는 특정 작업을 분리하여 처리할 수 있습니다.

단점:

  • 성능 저하: 특히 종속 서브쿼리(Correlated Subquery)는 각 행마다 서브쿼리를 실행하므로 성능이 저하될 수 있습니다. 큰 테이블에서 사용할 경우 성능 이슈가 발생할 수 있습니다.
  • 복잡성 증가: 서브쿼리를 많이 사용하면 쿼리가 복잡해져서 읽기 어려워질 수 있습니다.

서브쿼리와 조인의 비교

  • 서브쿼리는 중첩된 형태로 다른 쿼리의 결과를 참조하며, 주로 비교 연산이나 필터링을 위해 사용됩니다.
  • 조인(JOIN)은 여러 테이블의 데이터를 연결해서 반환하는 방식입니다. 서브쿼리 대신 조인을 사용할 수 있는 경우도 많습니다.

예시 (조인으로 대체 가능한 서브쿼리):

-- 서브쿼리 사용
SELECT name
FROM Employees
WHERE department_id IN (SELECT department_id FROM Departments WHERE location = 'New York');

이 쿼리는 서브쿼리를 통해 New York에 위치한 부서에 속한 직원을 조회합니다.

-- 조인 사용
SELECT e.name
FROM Employees e
JOIN Departments d ON e.department_id = d.department_id
WHERE d.location = 'New York';

같은 쿼리를 조인으로 바꿀 수 있습니다. 두 방식 모두 동일한 결과를 반환하지만, 서브쿼리와 조인은 성능이나 이해 측면에서 각각의 장단점이 있습니다.


요약

  • 서브쿼리는 다른 쿼리 내에서 중첩된 쿼리로, 특정 조건을 처리하거나 데이터를 참조하기 위해 사용됩니다.
  • 서브쿼리는 WHERE, FROM, SELECT, HAVING 절에서 사용될 수 있습니다.
  • 서브쿼리는 종속 서브쿼리비종속 서브쿼리로 나뉩니다.
  • 서브쿼리는 복잡한 조건을 처리하는 데 유용하지만, 성능에 영향을 줄 수 있으므로 조인과 서브쿼리의 적절한 사용을 고려해야 합니다.