[DB] CTE (a.k.a WITH์ ˆ)

iamhyunjiยท2022๋…„ 6์›” 2์ผ
0
post-thumbnail

๐Ÿ” ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—


์ตœ๊ทผ์— WITH์ ˆ๊ณผ ์ž„์‹œํ…Œ์—๋ธ”์˜ ์ฐจ์ด๋ฅผ ์ฐพ๋‹ค๊ฐ€ ๋ฌธ๋“ CTE๋ผ๋Š” ๊ฐœ๋…์„ ์ ‘ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.
CTE๋Š” ๋ฌด์—‡์ด๋ฉฐ, WITH์ ˆ๊ณผ CTE๋Š” ๋ฌด์Šจ ๊ด€๊ณ„๊ฐ€ ์žˆ๋Š”๊ฑธ๊นŒ?
์˜ค๋Š˜ ํฌ์ŠคํŒ…์—์„œ ์ž์„ธํžˆ ์•Œ์•„๋ณด์ž.

๐Ÿ“Œ CTE


CTE๋Š” Common Table Expressions์˜ ์•ฝ์ž์ด๋‹ค. CTE๋Š” SELECT, INSERT , UPDATE, DELETE์—์„œ ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ž„์‹œ์˜ ๊ฒฐ๊ณผ๊ฐ’์ด๋‹ค.

์กฐ๊ธˆ ๋” ํ’€์–ด ์„ค๋ช…ํ•˜๋ฉด, SELECT, INSERT , UPDATE, DELETE ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ, ํ•ด๋‹น ์ฟผ๋ฆฌ ๋‚ด๋ถ€์—์„œ CTE๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ํ…Œ์ด๋ธ”์ฒ˜๋Ÿผ ์˜๊ตฌ์ ์œผ๋กœ ์ €์žฅ๋˜๋Š”๊ฒŒ ์•„๋‹Œ ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๋™์•ˆ์—๋งŒ ์ž„์‹œ๋กœ ์กด์žฌํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ’์ด๋‹ค. ๋˜ํ•œ CTE๋Š” ์ž„์‹œ ๊ฒฐ๊ณผ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•ญ์ƒ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

CTE๋Š” ํฌ๊ณ  ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋‹จ์ˆœํ™”์‹œํ‚ค๋Š”๋ฐ ์œ ์šฉํ•˜๋ฉฐ, ์œ„๊ณ„ ๋˜๋Š” ๊ณ„์ธต์ด ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์กฐ์ž‘ํ•˜๋Š”๋ฐ ์ด์ ์ด ์žˆ๋‹ค.

์ข…๋ฅ˜๋กœ๋Š” ์•„๋ž˜ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

  • ์žฌ๊ท€์  CTE (Recursive)
  • ๋น„์žฌ๊ท€์  CTE (Non-Recursive)

์ด๋ฒˆ ํฌ์ŠคํŒ…์€ CTE์˜ ์ „๋ฐ˜์ ์ธ ๋‚ด์šฉ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•ด ๋น„์žฌ๊ท€์  CTE๋ฅผ ์ฃผ๋กœ ๋‹ค๋ฃจ๊ณ ์ž ํ•œ๋‹ค.

CTE๋Š” WITH์ ˆ์„ ํ†ตํ•ด ์ •์˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ์•„๋ž˜์—์„œ ์ž์„ธํžˆ ๋‹ค๋ค„๋ณด๊ณ ์ž ํ•œ๋‹ค.

๐Ÿ“Œ WITH์ ˆ


WITH [RECURSIVE]
        cte_name [(col_name [, col_name] ...)] AS (subquery)
        [, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...

WITH
  cte1 AS (SELECT a, b FROM table1),
  cte2 AS (SELECT c, d FROM table2)
SELECT b, d FROM cte1 JOIN cte2
WHERE cte1.a = cte2.c;

CTE๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • DML ์ฟผ๋ฆฌ ์ „์— ์ •์˜
  • WITH ํ‚ค์›Œ๋“œ๋กœ ์‹œ์ž‘
  • ์‚ฌ์šฉํ•  ์ด๋ฆ„์œผ๋กœ CTE ๋ช…๋ช…
  • CTE ์‚ฌ์šฉ ์‹œ ํ•„์š”ํ•œ ์ปฌ๋Ÿผ๋“ค ์ •์˜ (์„ ํƒ์‚ฌํ•ญ)
  • AS ํ‚ค์›Œ๋“œ
  • ํ•„์š”ํ•œ ์ฟผ๋ฆฌ๋ฌธ ์ž‘์„ฑ

CTE๋ฅผ ์ •์˜ํ•˜๊ณ ๋‚˜๋ฉด, DML์—์„œ ์›ํ•˜๋Š” ์œ„์น˜, ์›ํ•˜๋Š” ๋งŒํผ ์—ฌ๋Ÿฌ๋ฒˆ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

๐Ÿ“Œ ํŠน์ง•


  • ํ…Œ์ด๋ธ”์ฒ˜๋Ÿผ ์˜๊ตฌ์ ์œผ๋กœ ์ €์žฅ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, ์ฟผ๋ฆฌ ์‹คํ–‰ํ•  ๋•Œ์—๋งŒ ์ž„์‹œ์ ์œผ๋กœ ์กด์žฌ
  • ์ฟผ๋ฆฌ ๊ฐ€๋…์„ฑ ์ฆ๊ฐ€
  • ์ฟผ๋ฆฌ ๋‹จ์ˆœ์„ฑ ์ฆ๊ฐ€
  • ํ•˜๋‚˜์˜ ์ฟผ๋ฆฌ์—์„œ ์—ฌ๋Ÿฌ๋ฒˆ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • ์žฌ๊ท€์ ์œผ๋กœ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ’์— ์ ‘๊ทผ ๊ฐ€๋Šฅ
    ex) ๋Œ“๊ธ€์— ๋Œ“๊ธ€

๐Ÿ“Œ ํ™œ์šฉ ์˜ˆ์ œ


  • ํ…Œ์ด๋ธ” ๊ตฌ์„ฑ
# ํ•™์ƒ ํ…Œ์ด๋ธ”
CREATE TABLE STUDENT_MAST (
	STUDENT_ID VARCHAR(30) PRIMARY KEY
,	STUDENT_NAME VARCHAR(10)
,	CLASS_ID VARCHAR(30)
);

# ๊ต์‹ค ํ…Œ์ด๋ธ”
CREATE TABLE CLASS_ROOM_MAST (
	CLASS_ID VARCHAR(30) PRIMARY KEY
,	CLASS_NAME VARCHAR(10)
);

# ์„ฑ์  ํ…Œ์ด๋ธ”
CREATE TABLE EXAM_GRADE (
	STUDENT_ID VARCHAR(30) PRIMARY KEY
,	GRADE INT
);

# ๊ต์‹ค ๋ฐ์ดํ„ฐ ์„ธํŒ…
INSERT INTO CLASS_ROOM_MAST (CLASS_ID, CLASS_NAME) VALUES ('C01', '1๋ฐ˜');
INSERT INTO CLASS_ROOM_MAST (CLASS_ID, CLASS_NAME) VALUES ('C02', '2๋ฐ˜');
INSERT INTO CLASS_ROOM_MAST (CLASS_ID, CLASS_NAME) VALUES ('C03', '3๋ฐ˜');

# ํ•™์ƒ ๋ฐ์ดํ„ฐ ์„ธํŒ…
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S01', '๊ฐ•๋™์›', 'C01');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S02', '์ „์ง€ํ˜„', 'C01');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S03', '์ด๋™์šฑ', 'C01');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S04', '์œก์„ฑ์žฌ', 'C01');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S05', '์‹ ๋ฏผ์•„', 'C01');

INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S06', 'ํ‘œ์ง€ํ›ˆ', 'C02');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S07', '์ด์ œํ›ˆ', 'C02');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S08', 'ํ•œ์†Œํฌ', 'C02');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S09', '๊น€๊ฐ•์šฐ', 'C02');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S10', 'ํ•œ๊ฐ€์ธ', 'C02');

INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S11', '์ฃผ์œค๋ฐœ', 'C03');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S12', '์žฅ๊ตญ์˜', 'C03');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S13', '๊น€๋˜๊ฐ€', 'C03');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S14', '๊ฐ€์ง„๋™', 'C03');
INSERT INTO STUDENT_MAST (STUDENT_ID, STUDENT_NAME, CLASS_ID) VALUES ('S15', '์™•๋Œ€๋ฅ™', 'C03');

# ์„ฑ์  ๋ฐ์ดํ„ฐ ์„ธํŒ…
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S01', 81);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S02', 90);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S03', 75);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S04', 100);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S05', 87);

INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S06', 98);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S07', 70);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S08', 71);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S09', 65);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S10', 90);

INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S11', 60);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S12', 70);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S13', 100);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S14', 87);
INSERT INTO EXAM_GRADE (STUDENT_ID, GRADE) VALUES ('S15', 73);

# ๋ชจ๋“  ํ…Œ์ด๋ธ” ์ •๋ฆฌ
# DROP TABLE STUDENT_MAST, CLASS_ROOM_MAST, EXAM_GRADE;
  • ๋ฐ˜๋ณ„ ์„ฑ์  1๋“ฑ ํ•™์ƒ ๊ตฌํ•˜๋Š” ์ฟผ๋ฆฌ (๊ธฐ๋ณธํ˜•)
SELECT	VSM.CLASS_NAME
	,	VSM.STUDENT_NAME
    ,	VSM.GRADE
FROM (
	SELECT	CRM.CLASS_NAME
		,	CRM.CLASS_ID
		,	SM.STUDENT_ID
		,	SM.STUDENT_NAME
		,	ER.GRADE
		,	RANK() OVER(PARTITION BY SM.CLASS_ID ORDER BY ER.GRADE DESC) AS RANK_BY_CLASS
	FROM STUDENT_MAST SM
	INNER JOIN CLASS_ROOM_MAST CRM
		ON SM.CLASS_ID = CRM.CLASS_ID
	INNER JOIN EXAM_GRADE ER
		ON SM.STUDENT_ID = ER.STUDENT_ID
) VSM
WHERE RANK_BY_CLASS = 1
ORDER BY VSM.CLASS_ID ASC
;
  • ๋ฐ˜๋ณ„ ์„ฑ์  1๋“ฑ ํ•™์ƒ ๊ตฌํ•˜๋Š” ์ฟผ๋ฆฌ (CTE)
# CTE ์ •์˜
WITH STUDENT_RANK AS (
	SELECT	CRM.CLASS_NAME
		,	CRM.CLASS_ID
		,	SM.STUDENT_ID
		,	SM.STUDENT_NAME
		,	ER.GRADE
		,	RANK() OVER(PARTITION BY SM.CLASS_ID ORDER BY ER.GRADE DESC) AS RANK_BY_CLASS
	FROM STUDENT_MAST SM
	INNER JOIN CLASS_ROOM_MAST CRM
		ON SM.CLASS_ID = CRM.CLASS_ID
	INNER JOIN EXAM_GRADE ER
		ON SM.STUDENT_ID = ER.STUDENT_ID
)
# CTE ์‚ฌ์šฉ
SELECT	SR.CLASS_NAME
	,	SR.STUDENT_NAME
    ,	SR.GRADE
FROM STUDENT_RANK SR
WHERE SR.RANK_BY_CLASS = 1
ORDER BY SR.CLASS_ID ASC
;
  • ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ

โœ๐Ÿป ์˜ค๋Š˜์˜ ์ •๋ฆฌ


  • CTE๋Š” Common Table Expressions
  • ์ž„์‹œ์˜ ๊ฒฐ๊ณผ๊ฐ’
  • WITH์ ˆ์„ ์‚ฌ์šฉํ•ด CTE ์ •์˜
  • CTE์˜ ํŠน์ง•

๐Ÿ”— ์ฐธ๊ณ ยท์ถœ์ฒ˜


๐Ÿ‘€ ์Šค์Šค๋กœ ํ”ผ๋“œ๋ฐฑ


  • CTE์™€ ์ž„์‹œ ํ…Œ์ด๋ธ”์˜ ์ฐจ์ด์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ธฐ
  • ์žฌ๊ท€์  CTE (Recursive)์˜ ๊ฐœ๋…์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ธฐ
  • Derived Table์ด๋ž€ ๋ฌด์—‡์ธ์ง€
profile
Lv0. ์›น ๊ฐœ๋ฐœ (โค๏ธโค๏ธโค๏ธ๐Ÿค)

0๊ฐœ์˜ ๋Œ“๊ธ€