SQL에서 서브쿼리와 CTE
Source: Dev.to
SQL을 사용할 때 결국 단일 쿼리만으로는 충분하지 않은 상황에 직면하게 됩니다. 문제를 여러 부분으로 나누고, 중간 결과를 계산한 뒤 그 결과를 다른 곳에서 사용해야 합니다. 여기서 서브쿼리와 공통 테이블 식(CTE)이 등장합니다.
두 방법 모두 비슷한 문제를 해결하지만 약간 다른 방식으로 수행하며, 어느 것을 선택하느냐에 따라 성능, 가독성, 유지보수성에 영향을 줄 수 있습니다.
Source: …
Subqueries
서브쿼리는 다른 쿼리 안에 작성된 쿼리입니다. 외부 쿼리가 의존하는 결과를 생성하므로, 본질적으로 질문 안에 질문을 두는 형태입니다.
서브쿼리 작동 방식
- 배치 위치: 일반적으로
WHERE,SELECT,FROM절에 삽입되며, 역할에 따라 다릅니다. - 사용 사례: 결과가 한 번만 필요할 때 빠른 계산이나 필터링에 활용됩니다.
서브쿼리 종류
| Type | Description | Typical Use |
|---|---|---|
| Scalar subquery | 단일 값을 반환합니다. | 비교 연산 (예: WHERE salary > (SELECT AVG(salary) FROM employees)) |
| Multi‑row subquery | 여러 값을 반환합니다. | IN 같은 연산자 사용 (예: WHERE department_id IN (SELECT id FROM departments)) |
| Correlated subquery | 외부 쿼리의 컬럼을 참조하며, 각 행마다 한 번씩 실행됩니다. | 복잡한 필터링; 인덱스가 적절히 설정되지 않으면 느려질 수 있습니다 |
| Nested subquery | 다른 서브쿼리 안에 포함된 서브쿼리입니다. | 유효하지만 가독성이 떨어질 수 있어 리팩터링이 필요할 때가 많습니다 |
서브쿼리를 사용해야 할 때
- 로직이 비교적 단순할 때.
- 중간 결과가 한 번만 필요할 때.
- 별도의 이름을 지정하지 않고 간결한 쿼리를 만들고 싶을 때.
공통 테이블 식(CTEs)
CTE는 쿼리 시작 부분에 정의되는 이름이 있는 임시 결과 집합입니다. 한 번 정의하면 쿼리 전체에서 이름으로 참조할 수 있습니다.
CTE의 장점
- 논리를 이름이 있는 섹션으로 분리하여 가독성을 높입니다.
- 단계별로 쿼리를 구성할 수 있으며, 하나의 CTE가 다른 CTE에 의존할 수 있습니다.
- 동일한 중간 결과를 여러 번 재사용할 수 있습니다.
- 계층형 데이터(예: 조직도, 카테고리 트리)에 대한 재귀를 지원합니다.
CTE 유형
- Simple CTE – 단일 논리 블록의 가독성을 향상시킵니다.
- Multiple CTEs – 복잡한 변환을 위한 계층적 접근 방식; 각 CTE는 이전 CTE를 기반으로 구축될 수 있습니다.
- Recursive CTE – 자신을 반복적으로 참조하여 계층형 데이터를 처리합니다.
비교: 서브쿼리 vs. CTE
| 항목 | 서브쿼리 | CTE |
|---|---|---|
| 가독성 | 중첩이 깊어질수록 따라가기 어려워질 수 있음 | 구조화된 상향식 흐름; 디버깅이 더 쉬움 |
| 성능 | 단순 서브쿼리는 대개 최적화가 잘 되어 있지만, 상관 서브쿼리는 비용이 많이 들 수 있음 | DBMS에 따라 물리화될 수 있으며, 성능은 상황에 따라 다름 |
| 재사용성 | 보통 인라인으로 작성되며, 여러 곳에서 필요할 경우 중복이 발생함 | 한 번 정의하고 여러 번 참조함 |
| 복잡도 | 단순하고 일회성 계산에 적합 | 여러 단계나 재귀가 필요한 복잡한 쿼리에 더 적합 |
| 계층 구조 | 계층형 데이터에 적합하지 않음 | 재귀 CTE는 계층형 쿼리에 뛰어남 |
실제로 성능은 서브쿼리와 CTE 중 어느 것을 선택하느냐보다 쿼리 설계와 인덱싱에 더 크게 좌우됩니다.
언제 각각을 사용해야 할까요?
- Subqueries: 작업이 간단하고 결과가 한 번만 필요하며 간결한 쿼리를 선호할 때 선택합니다.
- CTEs: 로직이 복잡하고 가독성이 중요하거나 중간 결과를 재사용해야 하거나, 재귀가 필요한 계층형 데이터를 다룰 때 선호합니다.
Subqueries와 CTE는 직접적인 경쟁 관계라기보다 보완적인 도구입니다. 쿼리가 복잡해짐에 따라 서브쿼리로 시작했다가 CTE로 전환하는 경우가 흔하며, 이는 더 명확하고 유지보수가 쉬운 SQL을 만들게 합니다.