본문 바로가기

데이터베이스/SQLD

[SQLD] 서브 쿼리

728x90

서브쿼리란?

서브쿼리(Subquery)는 SQL 문 내부에 포함된 또 다른 SQL 문으로, 마치 함수가 특정 위치에 들어가는 것처럼 SQL 문 내에서 그 위치에 맞는 결과를 반환하는 독립적인 쿼리입니다. 서브쿼리는 메인 쿼리의 일부로 작동하며, 주로 복잡한 질의나 데이터를 더 세분화하여 조회할 때 사용됩니다.

서브쿼리의 종류

서브쿼리는 사용되는 위치와 반환되는 결과에 따라 여러 가지로 분류될 수 있습니다. 주요 서브쿼리의 종류는 다음과 같습니다:

  1. 스칼라 서브쿼리 (Scalar Subquery)
  2. 인라인 뷰 (Inline View)
  3. 중첩 서브쿼리 (Nested Subquery)

1. 스칼라 서브쿼리 (Scalar Subquery)

스칼라 서브쿼리는 하나의 값(스칼라 값)을 반환하는 서브쿼리입니다. 이 서브쿼리는 주로 SELECT, ORDER BY 절과 같은 컬럼이 들어갈 수 있는 위치에 사용됩니다. 중요한 점은, 스칼라 서브쿼리는 반드시 하나의 컬럼만 반환해야 하며, 결과도 오직 하나의 값이어야 한다는 것입니다.

예시:

SELECT 
    emp_name, 
    (SELECT dept_name FROM departments WHERE dept_id = employees.dept_id) AS department
FROM 
    employees;

이 예시에서 서브쿼리는 employees 테이블의 각 행에 대해 부서 이름을 반환합니다.

2. 인라인 뷰 (Inline View)

인라인 뷰는 테이블이 들어가는 위치에 사용되는 서브쿼리로, 주로 FROM 절에 위치합니다. 인라인 뷰는 쿼리 실행 시 동적으로 생성되는 테이블로 간주되며, 복잡한 쿼리를 단계적으로 작성할 때 유용합니다. 인라인 뷰를 사용하면, 전체 테이블을 비교하는 것이 아닌 필요한 부분만 비교하여 성능을 최적화할 수 있습니다.

예시:

SELECT 
    department, 
    AVG(salary) AS avg_salary
FROM 
    (SELECT dept_id, salary FROM employees WHERE salary > 50000) AS high_earners
GROUP BY 
    department;

이 예시에서 high_earners라는 이름의 인라인 뷰는 salary가 50,000 이상인 직원들을 필터링한 결과를 제공합니다.

3. 중첩 서브쿼리 (Nested Subquery)

중첩 서브쿼리는 조건절에 사용되는 서브쿼리로, 주로 WHERE 절과 HAVING 절에 위치합니다. 중첩 서브쿼리는 반환되는 결과의 형태에 제한이 없으며, 여러 가지 형태의 값을 반환할 수 있습니다. 이는 단일행, 다중행, 다중열을 반환할 수 있습니다.

중첩 서브쿼리의 유형:

  • 단일행 서브쿼리 (Single-row Subquery): 하나의 값만 반환하는 서브쿼리입니다. 주로 =, <, > 등의 단일행 비교 연산자와 함께 사용됩니다.
SELECT 
    emp_name
FROM 
    employees
WHERE 
    salary > (SELECT AVG(salary) FROM employees);

 

이 예시에서 서브쿼리는 전체 직원의 평균 급여를 계산하고, 메인 쿼리는 그 평균보다 급여가 높은 직원들을 조회합니다.

  • 다중행 서브쿼리 (Multi-row Subquery): 여러 행을 반환하는 서브쿼리입니다. IN, ALL, ANY 등의 다중행 비교 연산자와 함께 사용됩니다.
SELECT 
    emp_name
FROM 
    employees
WHERE 
    dept_id IN (SELECT dept_id FROM departments WHERE location = 'New York');

 

 

이 예시에서 서브쿼리는 뉴욕에 위치한 부서의 ID를 반환하고, 메인 쿼리는 해당 부서에 속한 직원들을 조회합니다.

  • 다중열 서브쿼리 (Multi-column Subquery): 여러 열을 반환하는 서브쿼리입니다. 이는 다중 열을 가진 테이블 형태로 결과가 반환됩니다.
SELECT 
    emp_name
FROM 
    employees
WHERE 
    (dept_id, salary) IN (SELECT dept_id, MAX(salary) FROM employees GROUP BY dept_id);

 

이 예시에서 서브쿼리는 각 부서에서 가장 높은 급여를 받는 직원들을 반환하고, 메인 쿼리는 해당 직원들의 이름을 조회합니다.

 

 

연관 서브쿼리와 비연관 서브쿼리

서브쿼리는 메인 쿼리 내부에 위치한 또 다른 쿼리로, 메인 쿼리의 조건을 세분화하거나 필요한 데이터를 추출하는 데 사용됩니다. 서브쿼리는 그 실행 방식에 따라 연관 서브쿼리비연관 서브쿼리로 나뉩니다.

1. 연관 서브쿼리 (Correlated Subquery)

연관 서브쿼리는 메인 쿼리의 각 행에 대해 서브쿼리가 반복적으로 실행되는 형태의 서브쿼리입니다. 서브쿼리는 메인 쿼리의 데이터를 참조하며, 그 결과는 메인 쿼리의 각 행에 따라 달라질 수 있습니다. 이러한 특징 때문에, 연관 서브쿼리는 메인 쿼리와 "연관"된 상태로 작동하게 됩니다.

예시:

SELECT 
    emp_name
FROM 
    employees e
WHERE 
    salary > (SELECT AVG(salary) FROM employees WHERE dept_id = e.dept_id);

이 예시에서 서브쿼리는 메인 쿼리의 dept_id 값을 참조하여 해당 부서의 평균 급여를 계산합니다. employees 테이블의 각 행에 대해 서브쿼리가 반복적으로 실행되며, 그 결과는 메인 쿼리의 조건에 따라 달라집니다.

연관 서브쿼리의 특징:

  • 메인 쿼리의 데이터를 참조하여 실행되므로, 각 행에 대해 다른 결과를 반환할 수 있습니다.
  • 반복적으로 실행되기 때문에 성능이 저하될 수 있습니다. 최적화를 위해 인덱스를 적절히 사용하는 것이 중요합니다.

2. 비연관 서브쿼리 (Non-Correlated Subquery)

비연관 서브쿼리는 메인 쿼리와 독립적으로 실행되는 서브쿼리입니다. 서브쿼리는 메인 쿼리의 데이터를 참조하지 않으며, 한 번 실행된 후 그 결과를 메인 쿼리가 참조하게 됩니다. 비연관 서브쿼리는 메인 쿼리와 "독립적"으로 작동하기 때문에 메인 쿼리와 연관되지 않습니다.

예시:

SELECT 
    emp_name
FROM 
    employees
WHERE 
    salary > (SELECT AVG(salary) FROM employees);

이 예시에서 서브쿼리는 전체 employees 테이블의 평균 급여를 계산합니다. 서브쿼리는 메인 쿼리와 독립적으로 실행되며, 그 결과는 메인 쿼리가 사용하게 됩니다.

비연관 서브쿼리의 특징:

  • 메인 쿼리의 데이터를 참조하지 않기 때문에, 서브쿼리는 메인 쿼리와 독립적으로 한 번만 실행됩니다.
  • 성능 상 이점이 있으며, 일반적으로 연관 서브쿼리보다 효율적입니다.

 

연관 서브쿼리와 비연관 서브쿼리의 비교

특징연관 서브쿼리비연관 서브쿼리

실행 방식 메인 쿼리의 각 행에 대해 서브쿼리가 반복 실행됨 서브쿼리가 한 번만 실행되고 그 결과를 사용함
메인 쿼리와의 관계 메인 쿼리의 데이터를 참조함 메인 쿼리와 독립적으로 실행됨
성능 상대적으로 성능이 저하될 수 있음 일반적으로 더 효율적

 

728x90

'데이터베이스 > SQLD' 카테고리의 다른 글

[SQLD] 집합연산자  (0) 2024.08.20
[SQLD] NULL 속성  (0) 2024.08.13
[SQLD] 트랜잭션  (0) 2024.08.02
[SQLD] 정규화  (1) 2024.07.30
[SQLD] Entity와 속성  (0) 2024.07.26