(→실전 활용:) |
|||
(같은 사용자의 중간 판 6개는 보이지 않습니다) | |||
3번째 줄: | 3번째 줄: | ||
|내용= WITH 절이란? | |내용= WITH 절이란? | ||
* (영문)The WITH clause lets you define a temporary result set (also called a CTE: Common Table Expression) that you can refer to within your main query. | * (영문)The WITH clause lets you define a temporary result set (also called a CTE: Common Table Expression) that you can refer to within your main query. | ||
* (한글)WITH 절은 | * (한글)WITH 절은 *임시 테이블(=서브쿼리 결과)을 먼저 정의하고, 그걸 메인 쿼리에서 재사용할 수 있게 해주는 문법이에요.또한, CTE 라고 불려요 | ||
}} | }} | ||
=== 왜 사용할까? === | === 왜 사용할까? === | ||
복잡한 서브쿼리를 미리 이름 붙여서 정리할 수 있음 | # 복잡한 서브쿼리를 미리 이름 붙여서 정리할 수 있음 | ||
# 가독성 좋아짐 | |||
가독성 좋아짐 | # 쿼리 재사용 가능 (같은 서브쿼리를 여러 번 쓰지 않아도 됨) | ||
# 중첩된 서브쿼리를 피할 수 있음 | |||
쿼리 재사용 가능 (같은 서브쿼리를 여러 번 쓰지 않아도 됨) | |||
중첩된 서브쿼리를 피할 수 있음 | |||
=== 기본 문법 === | === 기본 문법 === | ||
134번째 줄: | 131번째 줄: | ||
=== 주의사항 === | === 주의사항 === | ||
# Oracle 11g 이상부터 지원되며, Oracle 19c에서도 완벽히 사용 가능 | |||
# WITH 절은 SELECT, INSERT, UPDATE, DELETE에도 사용할 수 있음 | |||
# WITH 절 내 쿼리에는 ORDER BY를 직접 넣을 수 없음 (단, ROW_NUMBER()와 함께 정렬 가능) | |||
⸻ | ⸻ | ||
154번째 줄: | 151번째 줄: | ||
| 복잡한 쿼리 정리, 여러 조건 조합 분석 등 | | 복잡한 쿼리 정리, 여러 조건 조합 분석 등 | ||
|} | |} | ||
=== WITH 절 고급 === | === WITH 절 고급 === | ||
{{요점 | {{요점 | ||
|내용= WITH 재귀 쿼리란? | |내용= WITH 재귀 쿼리란? | ||
* 재귀 CTE(Common Table Expression) | * 재귀 CTE(Common Table Expression)는 WITH 절 안에서 자기 자신을 호출해서 계층적으로 데이터를 조회할 수 있는 기능입니다. | ||
* 주로 트리 구조, 부서-직원, 폴더-파일, 부모-자식 관계 등 계층형 데이터를 처리할 때 사용합니다. | * 주로 트리 구조, 부서-직원, 폴더-파일, 부모-자식 관계 등 계층형 데이터를 처리할 때 사용합니다. | ||
}} | }} | ||
285번째 줄: | 281번째 줄: | ||
⸻ | ⸻ | ||
CONNECT BY vs WITH 재귀 | ==== CONNECT BY vs WITH 재귀 ==== | ||
{| class="wikitable" style="width:100%;" | {| class="wikitable" style="width:100%;" | ||
! style="width:25%;" | 특징 | ! style="width:25%;" | 특징 | ||
! style="width:35%;" | CONNECT BY | ! style="width:35%;" | CONNECT BY | ||
! style="width:40%;" | WITH 재귀 | ! style="width:40%;" | WITH 재귀(CTE) | ||
|- | |- | ||
| '''문법''' | | '''문법''' | ||
316번째 줄: | 312번째 줄: | ||
==== 시나리오 1: 조직도 조회 (부서장 → 직원 트리 구조) ==== | ==== 시나리오 1: 조직도 조회 (부서장 → 직원 트리 구조) ==== | ||
상황 | 상황 | ||
# 인사팀에서 조직도를 트리 형태로 보고 싶어합니다. | |||
# employees 테이블에는 emp_id, name, manager_id가 있고, 누가 누구의 상사인지 정보가 들어 있습니다. | |||
쿼리 예제 | 쿼리 예제 | ||
341번째 줄: | 337번째 줄: | ||
==== 시나리오 2: 게시판 댓글 트리 조회 ==== | ==== 시나리오 2: 게시판 댓글 트리 조회 ==== | ||
상황 | 상황 | ||
# 게시판에서 댓글-대댓글 구조를 조회해야 합니다. | |||
# comments 테이블: comment_id, parent_id, content | |||
쿼리 예제 | 쿼리 예제 | ||
365번째 줄: | 361번째 줄: | ||
==== 시나리오 3: 제품 카테고리 분류 트리 ==== | ==== 시나리오 3: 제품 카테고리 분류 트리 ==== | ||
상황 | 상황 | ||
# 온라인 쇼핑몰에서 상품이 속한 카테고리를 트리로 관리하고 싶어요. | |||
# categories 테이블: category_id, parent_id, name | |||
쿼리 예제 | 쿼리 예제 | ||
390번째 줄: | 386번째 줄: | ||
==== 시나리오 4: 연속 날짜 생성 (캘린더 만들기) ==== | ==== 시나리오 4: 연속 날짜 생성 (캘린더 만들기) ==== | ||
상황 | 상황 | ||
# 날짜 기준 보고서 작성 시 날짜 테이블이 없으면 어려움. | |||
# WITH 절로 임시 날짜 테이블을 생성해서 활용 가능. | |||
쿼리 예제: 2024년 1월 1일~10일까지 날짜 생성 | 쿼리 예제: 2024년 1월 1일~10일까지 날짜 생성 | ||
411번째 줄: | 407번째 줄: | ||
==== 시나리오 5: 누적 매출 구하기 (누적합) ==== | ==== 시나리오 5: 누적 매출 구하기 (누적합) ==== | ||
상황 | 상황 | ||
# 시간 순으로 누적 매출을 보여줘야 하는 보고서. | |||
# sales 테이블: sale_date, amount | |||
<source lang=sql> | <source lang=sql> | ||
WITH daily_sales AS ( | WITH daily_sales AS ( | ||
433번째 줄: | 429번째 줄: | ||
---- | ---- | ||
시나리오 핵심 목적 활용 분야 | === 실전 활용 요약 === | ||
조직도 계층 구조 조회 인사 시스템 | |||
댓글 댓글-대댓글 구조 트리화 커뮤니티, 블로그 | {| class="wikitable" style="width:100%;" | ||
카테고리 분류 대/중/소 분류 트리화 쇼핑몰, 콘텐츠 플랫폼 | ! style="width:25%;" | 시나리오 | ||
날짜 생성 연속 날짜 생성 보고서, 캘린더, 출석부 | ! style="width:30%;" | 핵심 목적 | ||
누적 매출 시간 순 누적 값 계산 통계 보고서, 재무 데이터 | ! style="width:45%;" | 활용 분야 | ||
|- | |||
| '''조직도''' | |||
| 계층 구조 조회 | |||
| 인사 시스템 | |||
|- | |||
| '''댓글''' | |||
| 댓글-대댓글 구조 트리화 | |||
| 커뮤니티, 블로그 | |||
|- | |||
| '''카테고리 분류''' | |||
| 대/중/소 분류 트리화 | |||
| 쇼핑몰, 콘텐츠 플랫폼 | |||
|- | |||
| '''날짜 생성''' | |||
| 연속 날짜 생성 | |||
| 보고서, 캘린더, 출석부 | |||
|- | |||
| '''누적 매출''' | |||
| 시간 순 누적 값 계산 | |||
| 통계 보고서, 재무 데이터 | |||
|} | |||
[[category:oracle]] | [[category:oracle]] |
2025년 5월 18일 (일) 11:39 기준 최신판
WITH 절
menu_book WITH 절이란?
- (영문)The WITH clause lets you define a temporary result set (also called a CTE: Common Table Expression) that you can refer to within your main query.
- (한글)WITH 절은 *임시 테이블(=서브쿼리 결과)을 먼저 정의하고, 그걸 메인 쿼리에서 재사용할 수 있게 해주는 문법이에요.또한, CTE 라고 불려요
왜 사용할까?
- 복잡한 서브쿼리를 미리 이름 붙여서 정리할 수 있음
- 가독성 좋아짐
- 쿼리 재사용 가능 (같은 서브쿼리를 여러 번 쓰지 않아도 됨)
- 중첩된 서브쿼리를 피할 수 있음
기본 문법
WITH 임시이름 AS ( 서브쿼리 ) SELECT ... FROM 임시이름;
사용 예제
예제 테이블: sales
id | product | amount | year |
---|---|---|---|
1 | Laptop | 2000 | 2023 |
2 | Phone | 1500 | 2023 |
3 | Laptop | 2200 | 2024 |
4 | Phone | 1800 | 2024 |
5 | Laptop | 2500 | 2024 |
⸻
예제 1: 2024년 판매 데이터만 따로 떼어서 분석
WITH sales_2024 AS ( SELECT * FROM sales WHERE year = 2024 ) SELECT product, SUM(amount) AS total FROM sales_2024 GROUP BY product;
결과
product | total |
---|---|
Laptop | 4700 |
Phone | 1800 |
설명: WITH sales_2024라는 임시 테이블을 만들어 2024년 데이터만 분리하고, 그걸 기준으로 제품별 총 판매액을 계산했어요.
⸻
예제 2: WITH 절을 두 개 이상 사용하는 경우
WITH sales_2023 AS ( SELECT * FROM sales WHERE year = 2023 ), sales_2024 AS ( SELECT * FROM sales WHERE year = 2024 ) SELECT '2023' AS year, product, SUM(amount) AS total FROM sales_2023 GROUP BY product UNION ALL SELECT '2024' AS year, product, SUM(amount) AS total FROM sales_2024 GROUP BY product;
결과
year | product | total |
---|---|---|
2023 | Laptop | 2000 |
2023 | Phone | 1500 |
2024 | Laptop | 4700 |
2024 | Phone | 1800 |
설명: 연도별로 따로 나눈 데이터를 UNION ALL로 합쳐서 보여줍니다.
⸻
WITH 절 vs 서브쿼리
항목 | WITH 절 | 서브쿼리 |
---|---|---|
가독성 | 매우 높음 | 복잡하면 읽기 어려움 |
재사용 | 가능 (한 번 정의해서 여러 번 사용) | 동일 쿼리를 반복 작성해야 함 |
성능 | Oracle이 내부적으로 최적화 가능 | 중복 계산 발생 시 성능 저하 가능 |
주의사항
- Oracle 11g 이상부터 지원되며, Oracle 19c에서도 완벽히 사용 가능
- WITH 절은 SELECT, INSERT, UPDATE, DELETE에도 사용할 수 있음
- WITH 절 내 쿼리에는 ORDER BY를 직접 넣을 수 없음 (단, ROW_NUMBER()와 함께 정렬 가능)
⸻
요약 정리
개념 | 설명 |
---|---|
WITH 절 | 서브쿼리를 임시 테이블처럼 이름 붙여 사용 |
장점 | 쿼리 재사용, 가독성 향상, 유지보수 용이 |
사용 예 | 복잡한 쿼리 정리, 여러 조건 조합 분석 등 |
WITH 절 고급
menu_book WITH 재귀 쿼리란?
- 재귀 CTE(Common Table Expression)는 WITH 절 안에서 자기 자신을 호출해서 계층적으로 데이터를 조회할 수 있는 기능입니다.
- 주로 트리 구조, 부서-직원, 폴더-파일, 부모-자식 관계 등 계층형 데이터를 처리할 때 사용합니다.
기본 구조
WITH cte_name (컬럼들) AS ( -- anchor (기준이 되는 첫 번째 쿼리) SELECT ... FROM ... WHERE ... UNION ALL -- recursive (재귀적으로 자기 자신 호출) SELECT ... FROM 원본테이블 t JOIN cte_name c ON t.parent_id = c.id ) SELECT * FROM cte_name;
⸻
실전 예제: 조직도 계층 구조 조회
예제 테이블: employees
emp_id | name | manager_id |
---|---|---|
1 | CEO | NULL
|
2 | Alice | 1 |
3 | Bob | 1 |
4 | Carol | 2 |
5 | David | 2 |
6 | Eve | 3 |
⸻
목표
CEO → 부하 직원 → 그 밑 직원 순으로 전체 조직 계층도를 출력하고 싶어요.
⸻
쿼리
WITH org_chart (emp_id, name, manager_id, level) AS ( -- Anchor: 최상위 관리자 (CEO) SELECT emp_id, name, manager_id, 1 AS level FROM employees WHERE manager_id IS NULL UNION ALL -- Recursive: 상위 직원의 부하직원들 SELECT e.emp_id, e.name, e.manager_id, oc.level + 1 FROM employees e JOIN org_chart oc ON e.manager_id = oc.emp_id ) SELECT LPAD(' ', (level - 1) * 4) || name AS indented_name, level FROM org_chart ORDER BY level, emp_id;
⸻
결과
indented_name | level |
---|---|
CEO | 1 |
Alice | 2 |
Bob | 2 |
Carol | 3 |
David | 3 |
Eve | 3 |
설명: LPAD를 이용해서 직원 이름 앞에 공백을 넣어 들여쓰기 효과를 주었고, level을 이용해 계층을 구분했어요.
⸻
실전 활용:
메뉴 구조, 카테고리 분류, 댓글 트리 등
- 게시판 댓글 (대댓글)
- 온라인 쇼핑몰 카테고리 (대분류 > 중분류 > 소분류)
- 파일 시스템 (폴더 > 하위 폴더 > 파일)
- 사내 조직도
⸻
주의사항 (Oracle 19c 기준)
항목 | 설명 |
---|---|
RECURSIVE 키워드 | Oracle에서는 쓰지 않습니다. PostgreSQL 같은 DBMS에서만 필요합니다. |
UNION ALL 필수 | 재귀 CTE는 반드시 UNION ALL로 이어야 합니다. |
LEVEL, CONNECT BY | 기존의 Oracle 계층 쿼리 방식 (CONNECT BY)와도 유사한 역할을 합니다. |
⸻
CONNECT BY vs WITH 재귀
특징 | CONNECT BY | WITH 재귀(CTE) |
---|---|---|
문법 | Oracle 전용 문법 | 표준 SQL 방식 (Oracle에서도 지원됨) |
읽기 쉬움 | 간단하지만 복잡해지면 어려움 | 가독성 높음, 유연함 |
순서 제어 | ORDER SIBLINGS BY 필요 | 그냥 ORDER BY 사용 가능 |
컬럼 추가 유연성 | 낮음 | WITH에 원하는 컬럼 자유롭게 추가 가능 |
⸻
실전 시나리오별 WITH 절 (특히 재귀 CTE 포함)을 예제
시나리오 1: 조직도 조회 (부서장 → 직원 트리 구조)
상황
- 인사팀에서 조직도를 트리 형태로 보고 싶어합니다.
- employees 테이블에는 emp_id, name, manager_id가 있고, 누가 누구의 상사인지 정보가 들어 있습니다.
쿼리 예제
WITH org AS ( SELECT emp_id, name, manager_id, 1 AS level FROM employees WHERE manager_id IS NULL UNION ALL SELECT e.emp_id, e.name, e.manager_id, o.level + 1 FROM employees e JOIN org o ON e.manager_id = o.emp_id ) SELECT LPAD(' ', (level - 1) * 4) || name AS name, level FROM org ORDER BY level, emp_id;
활용 목적: 사내 인트라넷 조직도, 상하 관계 파악, 평가 구조 설계
시나리오 2: 게시판 댓글 트리 조회
상황
- 게시판에서 댓글-대댓글 구조를 조회해야 합니다.
- comments 테이블: comment_id, parent_id, content
쿼리 예제
WITH reply_tree AS ( SELECT comment_id, parent_id, content, 1 AS depth FROM comments WHERE parent_id IS NULL UNION ALL SELECT c.comment_id, c.parent_id, c.content, r.depth + 1 FROM comments c JOIN reply_tree r ON c.parent_id = r.comment_id ) SELECT LPAD(' ', (depth - 1) * 4) || content AS content_tree FROM reply_tree;
활용 목적: 커뮤니티 사이트, 포럼, 블로그 댓글 관리
시나리오 3: 제품 카테고리 분류 트리
상황
- 온라인 쇼핑몰에서 상품이 속한 카테고리를 트리로 관리하고 싶어요.
- categories 테이블: category_id, parent_id, name
쿼리 예제
WITH category_tree AS ( SELECT category_id, parent_id, name, 1 AS level FROM categories WHERE parent_id IS NULL UNION ALL SELECT c.category_id, c.parent_id, c.name, ct.level + 1 FROM categories c JOIN category_tree ct ON c.parent_id = ct.category_id ) SELECT LPAD(' ', (level - 1) * 2) || name AS category_path FROM category_tree ORDER BY level, name;
활용 목적: 카테고리 트리 메뉴 생성, 상품 등록 시 분류 관리
시나리오 4: 연속 날짜 생성 (캘린더 만들기)
상황
- 날짜 기준 보고서 작성 시 날짜 테이블이 없으면 어려움.
- WITH 절로 임시 날짜 테이블을 생성해서 활용 가능.
쿼리 예제: 2024년 1월 1일~10일까지 날짜 생성
WITH dates (dt) AS ( SELECT TO_DATE('2024-01-01', 'YYYY-MM-DD') FROM dual UNION ALL SELECT dt + 1 FROM dates WHERE dt + 1 <= TO_DATE('2024-01-10', 'YYYY-MM-DD') ) SELECT dt FROM dates;
활용 목적: 일별 매출 집계, 출근/결근 현황 분석, 캘린더 생성
시나리오 5: 누적 매출 구하기 (누적합)
상황
- 시간 순으로 누적 매출을 보여줘야 하는 보고서.
- sales 테이블: sale_date, amount
WITH daily_sales AS ( SELECT sale_date, amount FROM sales WHERE sale_date BETWEEN DATE '2024-01-01' AND DATE '2024-01-10' ), running_total AS ( SELECT ds1.sale_date, ds1.amount, (SELECT SUM(ds2.amount) FROM daily_sales ds2 WHERE ds2.sale_date <= ds1.sale_date) AS cumulative_total FROM daily_sales ds1 ) SELECT * FROM running_total ORDER BY sale_date;
활용 목적: 기간 누적 매출, 사용자 활동 누적, 진도율 계산 등
실전 활용 요약
시나리오 | 핵심 목적 | 활용 분야 |
---|---|---|
조직도 | 계층 구조 조회 | 인사 시스템 |
댓글 | 댓글-대댓글 구조 트리화 | 커뮤니티, 블로그 |
카테고리 분류 | 대/중/소 분류 트리화 | 쇼핑몰, 콘텐츠 플랫폼 |
날짜 생성 | 연속 날짜 생성 | 보고서, 캘린더, 출석부 |
누적 매출 | 시간 순 누적 값 계산 | 통계 보고서, 재무 데이터 |