Skip to content

Commit 3548c81

Browse files
[SQL] CTE 사용법 알아보기
1 parent bf18a54 commit 3548c81

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed

_posts/2025-07-27-cte.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
---
2+
layout: "post"
3+
title: "[SQL] CTE 사용법 알아보기"
4+
description:
5+
"CTE(Common Table Expression)는 SQL에서 복잡한 쿼리를 구조적으로 나누어 가독성과 재사용성을 높여주는 기능으로, \
6+
Oracle, SQL Server, PostgreSQL, MySQL 등 주요 데이터베이스에서 지원됩니다. \
7+
CTE는 WITH 절을 통해 정의되며, 파생 테이블과 유사하게 사용할 수 있습니다. \
8+
재귀 CTE를 활용하면 계층 구조 데이터 처리와 반복적인 계산을 간결하게 해결할 수 있습니다."
9+
categories:
10+
- "스터디-데이터베이스"
11+
tags:
12+
- "DATABASE"
13+
- "SQL"
14+
- "CTE"
15+
- "Common Table Expression"
16+
- "Derived Table"
17+
- "Subquery"
18+
- "Recursive CTE"
19+
- "Hierarchical Query"
20+
- "Anchor Query"
21+
- "JPA (ORM) 개발자를 위한 고성능 SQL"
22+
date: "2025-07-27 11:00:00 +0000"
23+
toc: true
24+
image:
25+
path: "/assets/thumbnails/2025-07-27-cte.jpg"
26+
---
27+
28+
# CTE 사용법 알아보기
29+
30+
**CTE****Common Table Expression** 의 약자이다. 한국말로는 **공통 테이블 표현식** 이라 한다.
31+
32+
CTE는 WITH절을 통해 정의하며, Oracle, SQL Server, PostgreSQL, MySQL, MariaDB 등 거의 모든 주요 데이터베이스에서 지원된다. (문법은 조금씩 차이가 있다.)
33+
MySQL 에서는 8.0 버전 부터 지원하고 있다.
34+
35+
## CTE
36+
37+
CTE의 장점은 가독성이 좋다는 점과, 여러 쿼리에서 동일한 CTE를 참조할 수 있다는 것이다.
38+
39+
대부분의 경우, CTE는 파생 테이블(Derived Table / Subquery)로 대체할 수 있으며 그 반대도 가능하다. 이전에 작성한 파생 테이블 쿼리도 동일하게 CTE 형식으로 나타낼 수 있으며, 대부분의 경우에도 성능이 동일하다.
40+
41+
> \[Note] 누군가 어떤 조언을 해주더라도 반드시 현재 사용 중인 데이터베이스에서 정확히 확인해야 한다. 최적화는 가정에 기반한다. 따라서, 쿼리가 잘 작동하는지 여부를 증명하는 유일한 방법은 다시 실행 계획을 확인하는 것이다.
42+
43+
CTE를 사용하여 하나의 쿼리에서 여러 CTE를 선언할 수 있고, 이전에 정의한 CTE를 또 다른 CTE에서 참조하여 사용할 수 있다.
44+
45+
CTE에서 정의된 쿼리들은 현재 SQL 실행 문(statement)의 범위에서만 유효하며, 메모리 내에서 일시적으로만 존재한다.
46+
47+
### 같은 쿼리를 Derived Table 와 CTE 로 비교
48+
49+
댓글이 가장 많은 상위 세 개의 게시물의 제목 조회하는 SQL 예시이다.
50+
51+
#### Derived Table
52+
53+
```sql
54+
SELECT
55+
p.title AS post_title,
56+
pc.comment_count AS comment_count
57+
FROM post p
58+
JOIN (
59+
SELECT
60+
post_id,
61+
COUNT(*) as comment_count
62+
FROM post_comment
63+
GROUP BY post_id
64+
ORDER BY comment_count DESC
65+
LIMIT 3
66+
) pc ON p.id = pc.post_id
67+
ORDER BY comment_count DESC
68+
```
69+
70+
#### CTE
71+
72+
```sql
73+
WITH TopCommentedPosts AS (
74+
SELECT
75+
post_id,
76+
COUNT(*) AS comment_count
77+
FROM post_comment
78+
GROUP BY post_id
79+
ORDER BY comment_count DESC
80+
LIMIT 3
81+
)
82+
SELECT
83+
p.title AS post_title,
84+
tcp.comment_count AS comment_count
85+
FROM post p
86+
JOIN TopCommentedPosts tcp ON p.id = tcp.post_id
87+
ORDER BY tcp.comment_count DESC;
88+
```
89+
90+
## Recursive CTE (재귀적 CTE)
91+
92+
Recursive CTE 를 사용하면 이론적으로 모든 계산 가능한 문제를 해결할 수 있다. (튜링 완전)
93+
94+
절차적 언어(Java 등)에서 반복문을 이용하는 것과 유사하며, 이를 통해 일반적인 데이터 처리와 계층 구조 데이터를 쉽게 해결할 수 있다.
95+
96+
### 예시: 연속된 숫자의 합 구하기
97+
98+
```sql
99+
WITH RECURSIVE
100+
consecutive_number_sum (i, consecutive_sum)
101+
AS (
102+
SELECT 0, 0
103+
UNION ALL
104+
SELECT i + 1, (i + 1) + consecutive_sum
105+
FROM consecutive_number_sum
106+
WHERE i < :n
107+
)
108+
```
109+
110+
`n` 이 5일 때 다음과 같은 결과가 나온다.
111+
112+
| i | consecutive_sum |
113+
| --- | --------------- |
114+
| 0 | 0 |
115+
| 1 | 1 |
116+
| 2 | 3 |
117+
| 3 | 6 |
118+
| 4 | 10 |
119+
| 5 | 15 |
120+
121+
#### 구조 이해하기
122+
123+
- **Anchor Query**: 첫번째 SELECT 문을 의미. 재귀의 시작값(예: i = 0, sum = 0)을 정의.
124+
- **UNION ALL**: 각 단계마다 새로운 레코드를 결과 집합에 추가
125+
- **recursive member**: 두번째 SELECT 문을 의미한다. 앞선 결과(i, sum 값)를 기반으로 값을 누적하며 반복 실행(i가 5에 도달할 때까지 등)
126+
- 재귀 멤버의 WHERE 절로 반복 범위를 제어할 수 있다.
127+
128+
### 예시: Hierarchical Query - 계층구조 데이터 조회
129+
130+
댓글처럼 트리 형태로 계층이 구성될 때 (ex. 자식 댓글이 부모 댓글을 참조, 대댓글) CTE를 사용하여 데이터를 조회할 수 있다.
131+
132+
```sql
133+
WITH RECURSIVE comment_tree(
134+
id, root_id, post_id, parent_id, review, created_on)
135+
AS (
136+
SELECT
137+
id, id, post_id, parent_id, review, created_on
138+
FROM post_comment
139+
WHERE post_id = :postId AND parent_id IS NULL
140+
UNION ALL
141+
SELECT pc.id, ct.root_id, pc.post_id, pc.parent_id,
142+
pc.review, pc.created_on
143+
FROM post_comment pc
144+
INNER JOIN comment_tree ct ON pc.parent_id = ct.id
145+
)
146+
SELECT id, parent_id, root_id, review, created_on
147+
FROM comment_tree
148+
```
149+
150+
## 마무리
151+
152+
CTE(Common Table Expression)는 복잡한 SQL 쿼리를 구조적으로 나누어 가독성과 재사용성을 높여주는 유용한 기능입니다. 일반적인 서브쿼리와 유사하게 사용할 수 있을 뿐만 아니라, 재귀 CTE를 활용하면 계층 구조나 반복적인 계산과 같은 복잡한 데이터 처리도 SQL만으로 간결하게 해결할 수 있습니다.
1.54 MB
Loading

0 commit comments

Comments
 (0)