2025.02.16 - [자격증/SQLD] - Part 4: SQL 활용 (Advanced SQL Usage)
[SQLD] Chapter 4-1: 서브쿼리 (Subquery)
1. 서브쿼리의 정의와 특징
1.1 서브쿼리란?
서브쿼리(Subquery)는 SQL 문 내에서 또 다른 SQL 문을 중첩하여 사용하는 방식입니다. 하나의 SQL 문에서 또 다른 SQL 문을 실행하여 원하는 데이터를 조회, 삽입, 수정, 삭제하는 데 사용됩니다.
서브쿼리는 SELECT, INSERT, UPDATE, DELETE 등의 SQL 문에서 사용할 수 있으며, 주로 조건 필터링, 데이터 검색, 값 비교 등의 목적으로 활용됩니다.
1.2 서브쿼리의 특징
- 중첩된 SELECT 문: SQL 문 안에서 또 다른 SELECT 문을 실행
- 메인 쿼리의 데이터를 보조하는 역할
- 단일 행 또는 다중 행 값을 반환할 수 있음
- 연산자와 함께 사용 가능 (IN, EXISTS, =, <, >, ANY, ALL 등)
- 독립적으로 실행되는 비연관 서브쿼리와, 메인 쿼리와 연관된 연관 서브쿼리가 있음
2. 연관 서브쿼리vs. 비연관 서브쿼리
2.1 비연관 서브쿼리 (Non-Correlated Subquery)
비연관 서브쿼리는 메인 쿼리와 독립적으로 실행되며, 한 번만 실행된 후 그 결과가 메인 쿼리에 전달됩니다.
예제: 최고 연봉을 받는 직원 조회
EMPLOYEES 테이블
EMPLOYEE_ID | EMPLOYEE_NAME | SALARY |
1 | 홍길동 | 3000 |
2 | 김철수 | 4500 |
3 | 이영희 | 6000 |
SELECT EMPLOYEE_NAME, SALARY
FROM EMPLOYEES
WHERE SALARY = (SELECT MAX(SALARY) FROM EMPLOYEES);
결과
EMPLOYEE_NAME | SALARY |
이영희 | 6000 |
✅ 설명
- 서브쿼리는 독립적으로 한 번만 실행되며, 최고 연봉을 반환
- 메인 쿼리는 이 값을 기준으로 해당 연봉을 받는 직원을 조회
2.2 연관 서브쿼리 (Correlated Subquery)
연관 서브쿼리는 메인 쿼리의 각 행을 처리할 때마다 실행되며, 메인 쿼리의 값을 서브쿼리가 참조합니다.
예제: 각 직원이 속한 부서의 평균 급여보다 높은 직원 조회
EMPLOYEES 테이블
EMPLOYEE_ID | EMPLOYEE_NAME | SALARY |
1 | 홍길동 | 3000 |
2 | 김철수 | 4500 |
3 | 이영희 | 6000 |
SELECT EMPLOYEE_NAME, SALARY
FROM EMPLOYEES E
WHERE SALARY > (SELECT AVG(SALARY)
FROM EMPLOYEES
WHERE DEPARTMENT_ID = E.DEPARTMENT_ID);
결과
EMPLOYEE_NAME | SALARY |
이영희 | 6000 |
✅ 설명
- 서브쿼리는 각 직원의 DEPARTMENT_ID를 사용하여 해당 부서의 평균 급여를 계산
- 메인 쿼리는 직원의 급여가 해당 부서의 평균 급여보다 높은 경우만 출력
3. 단일 행 서브쿼리 vs. 다중 행 서브쿼리
구분 | 단일 행 서브 쿼리 | 다중행 서브쿼리 |
반환 값 개수 | 1개 (1행 1열) | 여러 개 (여러 행 1열) |
사용 연산자 | =, <, >, <=, >= | IN, ANY, ALL |
주의❗
단일항 비교 연산자 (=, <, > 등)은 다중행 비교 연산자가 될 수 없지만,
다중항 비교 연산자 (IN, ANY, ALL)은 단일행 비교 연산자로 쓸 수 있다 (return 값이 1일 경우).
3.1 단일 행 서브쿼리 (Single-row Subquery)
- 서브쿼리가 오직 하나의 값(1행 1열)을 반환하는 경우
- 단일 행 비교 연산자 (=, <, >, <=, >= 등) 와 함께 사용됨
예제: 최고 연봉을 받는 직원 조회
EMPLOYEES 테이블
EMPLOYEE_ID | EMPLOYEE_NAME | SALARY |
1 | 홍길동 | 3000 |
2 | 김철수 | 4500 |
3 | 이영희 | 6000 |
SELECT EMPLOYEE_NAME, SALARY
FROM EMPLOYEES
WHERE SALARY = (SELECT MAX(SALARY) FROM EMPLOYEES);
결과
EMPLOYEE_NAME | SALARY |
이영희 | 6000 |
3.2 다중 행 서브쿼리 (Multi-row Subquery)
- 서브쿼리가 여러 개의 행을 반환할 수 있음
- 다중행 비교 연산자 (IN, ANY, ALL) 연산자와 함께 사용됨
예제: 특정 부서의 모든 직원 조회
EMPLOYEES 테이블
EMPLOYEE_ID | EMPLOYEE_NAME | SALARY |
1 | 홍길동 | 3000 |
2 | 김철수 | 4500 |
3 | 이영희 | 6000 |
SELECT EMPLOYEE_NAME, SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID IN (SELECT DEPARTMENT_ID FROM DEPARTMENTS WHERE LOCATION = 'SEOUL');
결과
EMPLOYEE_NAME | SALARY |
홍길동 | 3000 |
이영희 | 6000 |
✅ 설명
- 서브쿼리는 DEPARTMENTS 테이블에서 서울에 위치한 부서 ID를 여러 개 반환
- 메인쿼리는 EMPLOYEES 테이블에서 해당 부서에 속한 직원들을 출력
4. 스칼라 서브쿼리 (Scalar Subquery)
- 특징:
- 서브쿼리가 단일 값(One Row, One Column)만 반환하는 형태.
- 일반적으로 SELECT 절 또는 WHERE 절에서 사용됨.
- 단일 행을 반환하는 특성 때문에 여러 행을 반환하면 에러 발생 가능.
- 예제:
- 서브쿼리가 전체 직원의 평균 급여를 반환하며, 이를 SELECT 절에서 사용하여 각 직원과 비교할 수 있음.
SELECT emp_name, salary,
(SELECT AVG(salary) FROM employees) AS avg_salary
FROM employees;
5. EXISTS / NOT EXISTS 활용
- EXISTS: 서브쿼리에서 값이 존재하면 참
- NOT EXISTS: 서브쿼리에서 값이 없으면 참
예제: 주문이 존재하는 고객 조회
CUSTOMERS 테이블
CUSTOMER_ID | NAME |
101 | 홍길동 |
102 | 김철수 |
103 | 이영희 |
ORDERS 테이블
ORDER_ID | CUSTOMER_ID | AMOUNT |
1 | 101 | 500 |
2 | 103 | 1000 |
SELECT NAME
FROM CUSTOMERS C
WHERE EXISTS (
SELECT 1
FROM ORDERS O
WHERE C.CUSTOMER_ID = O.CUSTOMER_ID
);
결과
NAME |
홍길동 |
이영희 |
✅ 설명
- EXISTS를 사용하여 ORDERS 테이블에 해당 고객의 주문이 존재하는 경우만 출력
6. 서브쿼리와 JOIN 비교
서브쿼리는 쿼리 안에 또 다른 쿼리를 포함하는 방식이지만, 때때로 JOIN을 사용하여 같은 결과를 얻을 수 있습니다.
CUSTOMERS 테이블
CUSTOMER_ID | NAME |
101 | 홍길동 |
102 | 김철수 |
103 | 이영희 |
ORDERS 테이블
ORDER_ID | CUSTOMER_ID | AMOUNT |
1 | 101 | 500 |
2 | 103 | 1000 |
서브쿼리 사용 예제
SELECT NAME
FROM CUSTOMERS
WHERE CUSTOMER_ID IN (SELECT CUSTOMER_ID FROM ORDERS);
JOIN 사용 예제
SELECT C.NAME
FROM CUSTOMERS C
JOIN ORDERS O ON C.CUSTOMER_ID = O.CUSTOMER_ID;
결과 테이블 (두 방법 동일한 결과)
NAME |
홍길동 |
이영희 |
✅ JOIN을 사용하면 서브쿼리보다 성능이 더 좋을 수 있음 (특히 대용량 데이터에서 유리)
7. 마무리
이번 장에서는 서브쿼리(Subquery)의 개념과 종류를 자세히 살펴보았습니다.
✅ 서브쿼리의 기본 개념
- 서브쿼리는 SQL 문 내부에서 또 다른 SQL 문을 실행하는 구조로, 데이터를 보다 정교하게 조회할 수 있도록 도와줍니다.
✅ 연관 서브쿼리 vs. 비연관 서브쿼리
- 비연관 서브쿼리는 메인 쿼리와 독립적으로 한 번만 실행됩니다.
- 연관 서브쿼리는 메인 쿼리의 각 행마다 반복 실행되므로 성능에 주의해야 합니다.
✅ 단일 행 서브쿼리 vs. 다중 행 서브쿼리
- 단일 행 서브쿼리는 한 개의 값만 반환하며, =, <, >, <=, >= 연산자와 함께 사용됩니다.
- 다중 행 서브쿼리는 여러 개의 값을 반환할 수 있으며, IN, ANY, ALL 연산자와 함께 사용됩니다.
- 단일 행 비교 연산자(=, <, >)는 ANY, ALL과 결합하면 다중 행과 비교할 수도 있습니다.
✅ EXISTS / NOT EXISTS 활용
- EXISTS는 서브쿼리에서 값이 존재하면 TRUE, NOT EXISTS는 값이 없으면 TRUE를 반환하여 조건 필터링에 유용합니다.
✅ 서브쿼리 vs. JOIN 비교
- 서브쿼리는 특정 조건을 만족하는 데이터를 찾는 데 효과적이지만, JOIN을 사용하면 성능이 더 좋을 수 있습니다.
- 대용량 데이터에서는 JOIN을 적극적으로 고려하는 것이 성능 최적화에 유리합니다.
📌 다음 장에서는 뷰(View)에 대해 다룰 예정입니다.
💡 도움이 되셨다면 댓글과 공감 부탁드립니다! 😊
📌 더 많은 알고리즘 풀이와 프로그래밍 자료는 블로그에서 확인하세요!
✉️ 문의나 피드백은 댓글이나 이메일로 남겨주세요.
'자격증 > SQLD' 카테고리의 다른 글
[SQLD] 4-3: 집합 연산자 (Set Operators) (0) | 2025.02.17 |
---|---|
[SQLD] 4-2: 뷰 (View) (0) | 2025.02.17 |
Part 4: SQL 활용 (Advanced SQL Usage) (0) | 2025.02.16 |
[SQLD] 3-3: 논리적 JOIN (조인)의 모든 것 (0) | 2025.02.16 |
[SQLD] 3-2: GROUP BY & HAVING & ORDER (0) | 2025.02.16 |