
์ด๋ ค์์ ๋ฏธ๋ฃจ๋ค๊ฐ ๋ชป ํผ ๋ฌธ์ ๊ฐ 2๊ฐ ์์๋ค. Lv4 ๋ฌธ์ 1๊ฐ๋ Lv5 ๋ฌธ์ 1๊ฐ์ด๋ค. ๋์ด๋ ์ต์์ธ ๋งํผ, ๋ฌธ์ ์ฝ๊ธฐ๋ ์ ์ ํ๊ธฐ๊ฐ ๋๋ ค์ด ๋ง์์ด ์์๋ค. ์ด ๋ฌธ์ ๋ ์ ์ง ์ค๋ซ ๋์ ๋ ธํธ๋ถ ์์ ์์์ ๋จธ๋ฆฌ ๋ง์ด ์ฐ๊ณ ๊ณ ๋ฏผํด ๋ด์ผ ๋ ๊ฒ ๊ฐ์์ ํ๊ธฐ์ซ์๋ค. MySQL์์๋ START WITH CONNECT BY๊ฐ ์๋๋ค๋ ๊ฑฐ ์๊ณ ๋ถํฐ๋ ๋ ์๋ก์ด๊ฑฐ ๋ฐฐ์ฐ๊ธฐ ์ซ์ด์ ๋ฏธ๋ค๋๋ฐ ์ค๋ ์ผ๋ฅธ ๋๋ด๋ฒ๋ฆฌ๊ณ ์์ผ์ง
1. ๋ฌธ์ ์ค๋ช

2. ์ ๊ทผ๋ฐฉ์
์ฒ์์๋ ์ด๋ ค์ ๋ณด์ฌ์ ๋ฌธ์ ๋ฅผ ์ฝ๊ณ ๋ญ ๊ตฌํด์ผ ํ๋์ง ์๊ฐ์ ํ๋ฆ์ ํ๊ธ๋ก ๋ฐ์ ์ ์ด ๋ดค๋ค.
PARENT_ID๊ฐ NULL์ด๋ฉด 1์ธ๋์ด๋ค.
PARENT_ID๊ฐ NULL์ธ ID๋ฅผ ๋ถ๋ชจ๋ก ๊ฐ์ง๋ ํ์ด 2์ธ๋ ์ด๋ค.
PARENT_ID๊ฐ NULL์ธ ID๋ฅผ ๋ถ๋ชจ๋ก ๊ฐ์ง๋ ํ์ ID๋ฅผ ๋ถ๋ชจ๋ก ๊ฐ์ง๋ ํ์ด 3์ธ๋ ์ด๋ค.
์ฌ๊ธฐ๊น์ง ๋ฐ์ ์ ์ผ๋๊น ๊ณ์ธต์ฟผ๋ฆฌ์ธ๋ฐ
START WITH PARENT_ID IS NULL ๋ก ์์ํ๊ณ LV์ด 3์ธ ID๋ง ์กฐํํ๋ฉด ๋๊ฒ ๋ค๋ ์๊ฐ์ด ๋ ์ฌ๋๋ค!
์ฒ์์๋ ์ด๊ฑธ ํ๋ ํ๋ ๋ฐ๋ผ๊ฐ๋ฉด์ ๊ณ์ฐํด์ค์ผ ํ๋ค๋ ์๊ฐ์
์ฟผ๋ฆฌ๋ ๊ธธ์ด์ง ๊ฒ ๊ฐ๊ณ ์ค๋๊ฑธ๋ฆด ๊ฑฐ ๊ฐ๋ค ์๊ฐํ๋๋ฐ
์ค๋ง ์ด๋ ๊ฒ ์ฝ๊ฒ ํ๋ฆฐ๋ค๊ณ ??
SELECT ID
FROM ECOLI_DATA
START WITH PARENT_ID IS NULL
CONNECT BY PRIOR ID = PARENT_ID
AND LEVEL = 3
ORDER BY ID;

์์ ์๊ฒ ์ฝ๋๋ฅผ ์ผ์ผ๋ ๋ด๊ฐ ์๋ START WITH CONNECT BY๋ MySQL ๋ฌธ๋ฒ์ด ์๋๋ผ๋ Syntax Error์ด ๋ธ? ์ค๋ผํด์์๋ง ๋๋ ๊ฑฐ๊ตฌ๋. ๊ทธ๋ผ ์ด๊ฑธ ๋ค์ MySQL์์ผ๋ก ๋ณํํด์ผ ํ๋ค. Oracle ๋ก ๋ต์ ์ ์ถํ๋ ์ต์
์ด ์์ด์ ์ด์ฉ ์ ์์ด MySQL๋ฌธ๋ฒ์ ๊ฒ์ํด ๋ณด์๋ค. ์ค๋ผํด๋ณด๋ค ์ฝ๋๋ ํจ์ฌ ๊ธธ์ด์ง ๊ฒ ๊ฐ์ง๋ง
๊ฐ๋ณด์๊ตฌ
โญ WITH RECURSIVE
MySQL์์ ๊ณ์ธต์ฟผ๋ฆฌ๋ฅผ ์กฐํํ๋ ค๋ฉด `WITH RECURSIVE`๋ผ๋ ๊ฑธ ์จ ์ค์ผ ํ๋ค.
์กฐ๊ธ ์ด๋ ค์ด๋ฐ WITH RECURSIVE๋ก ์ฌ๊ท์ CTE๋ฅผ ์ ์ํด ์ฃผ๋ ๊ฒ์ด๋ค.
CTE๋ ๊ณต๋ํ
์ด๋ธ ํํ์์ด๋ค. CTE(Common Table Expression)๋ ์ผ์์ ์ธ ๊ฒฐ๊ณผ ์งํฉ์ ๋ง๋ค์ด ์ค๋ค. ๊ทธ๋ฆฌ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ฟผ๋ฆฌ์ ๋ค๋ฅธ ๋ถ๋ถ์์ ์ฐธ์กฐํ ์ ์๊ฒ ํด์ฃผ๋ ๊ตฌ์กฐ์ด๋ค. ์๋ธ์ฟผ๋ฆฌ๋ ๋น์ทํ์ง๋ง ์ฐจ์ด๊ฐ ์๋ค.
์๋๋ ChatGPT๊ฐ CTE์ ์๋ธ์ฟผ๋ฆฌ๋ฅผ ๋น๊ต ํด ์ค ๋ด์ฉ์ด๋ค.
โญ CTE (Common Table Expression)๋?
- ์ฟผ๋ฆฌ ์ธ๋ถ์์ ์ ์๋๊ณ , ์ฟผ๋ฆฌ ๋ณธ๋ฌธ์์ ์ฐธ์กฐ๋๋ค.
- WITH ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ํ๋ค.
- ์ฌ์ฌ์ฉํ ์ ์๋ ์ผ์์ ์ธ ๊ฒฐ๊ณผ ์งํฉ์ ๋ง๋ ๋ค.
- ํ ๋ฒ ์ ์๋ ํ, ๋ค์ํ ๋ถ๋ถ์์ ์ฐธ์กฐํ ์ ์๋ค.
- ์ฌ๊ท์ ์ฟผ๋ฆฌ์์ ์์ฃผ ์ฌ์ฉ๋๋ค.
WITH CTE_NAME AS (
SELECT column1, column2
FROM some_table
WHERE condition
)
SELECT * FROM CTE_NAME;
๋ฐ๋ฉด ์๋ธ์ฟผ๋ฆฌ๋?
- ์ฟผ๋ฆฌ ๋ด์์ ์ค์ฒฉ๋ ์ฟผ๋ฆฌ
- SELECT, FROM, WHERE ๋ฑ์ ๋ถ๋ถ์์ ์ฌ์ฉ๋๋ค.
- CTE์ ๋ฌ๋ฆฌ ์ฟผ๋ฆฌ์ ์ผ๋ถ๋ก ํฌํจ๋๋ฉฐ, ํ ๋ฒ๋ง ์คํ๋๋ค.
- ์๋ธ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ๋ ์ฟผ๋ฆฌ ๋ณธ๋ฌธ์์ ํ ๋ฒ๋ง ์ฐธ์กฐ๋๋ค.
SELECT column1
FROM some_table
WHERE column2 IN (
SELECT column2
FROM another_table
WHERE condition
);
์ฌ๊ธฐ๊น์ง ChatGPT์ ์์ธํ๊ณ ์น์ ํ ์ค๋ช
์ด์๋ค.
๋๋ ์ด๊ฑธ ์ฝ๊ณ ๋ง์ด ๋ฐฐ์ ๋ค.
์ด์ด์
WITH RECURSIVE๋ก ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๋ง๋๋ ์๋ฆฌ๋ฅผ ๊ฐ๋จํ๊ฒ ์ค๋ช
ํด ๋ณด๋ฉด
๋จผ์ , PARENT_ID IS NULL์ธ 1์ธ๋ ๋์ฅ๊ท ์ ์ฐพ๋๋ค.(AS Generation)
SELECT ID, PARENT_ID, 1 AS GENERATION
FROM ECOLI_DATA
WHERE PARENT_ID IS NULL
์ฌ๊ธฐ์ ์ค์ํ ๊ฒ์ ์ฌ๊ธฐ์์๋ WITH RECURSIVE ๊ตฌ๋ฌธ ๋ด์์ ์ฒซ๋ฒ์งธ ๊ณ์ธต์ด ์์๋๋ ์ง์ ์์ AS GENERATION์ด๋ผ๋ ๋ณ์นญ์ ์ฃผ์๋ค๋ ๊ฒ์ด๋ค. ์ฆ, ์ฌ๊ท ์ฟผ๋ฆฌ์์ ๊ฐ ๋์ฅ๊ท ์ด ๋ช ๋ฒ์งธ ์ธ๋์ ์ํ๋์ง๋ฅผ ์ถ์ ํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ์์ ์ปฌ๋ผ์ ๋ง๋ค์ด ์ค ๊ฒ์ด๋ค.
WITH RECURSIVE ์ฟผ๋ฆฌ์์๋ ๋ณดํต ์ฒซ ๋ฒ์งธ ๊ณ์ธต์์ ์ด๊ธฐ ๊ฐ์ ์ง์ ํ๊ณ , ๋ ๋ฒ์งธ ๊ณ์ธต(์์ ๋์ฅ๊ท )์์ ๊ทธ ๊ฐ์ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ฆ๊ฐ์ํค๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ค.
๊ทธ ๋ค์์๋ Generation์ ID์ ECOLI_DATA์ PARENT_ID๋ก JOIN ํด ์ค๋ค.
Generation๊ฐ์ + 1 ์ ํด ์ฃผ๋ฉด 2์ธ๋, 3์ธ๋, ๋ฑ ์ฐ๊ฒฐ๋ ๋ชจ๋ ์ธ๋๊ฐ์ด ๋์ค๊ฒ ๋๋ค.
SELECT e.ID, e.PARENT_ID, g.GENERATION + 1
FROM ECOLI_DATA e
JOIN Generation g ON e.PARENT_ID = g.ID
์ด ๋ ๊ฐ๋ฅผ UNION ALL ํด ์ฃผ๋ฉด ์ฐ๊ฒฐ๋ ๊ณ์ธต๊ตฌ์กฐ๋ฅผ ๊ฐ์ง ๋ฐ์ดํฐ ์งํฉ์ด ์์ฑ๋๋ค.
WITH RECURSIVE Generation AS (
-- ์ฒซ ๋ฒ์งธ ์ฟผ๋ฆฌ: ๋ถ๋ชจ ๋์ฅ๊ท (์ฒซ ๋ฒ์งธ ์ธ๋) ์ฐพ๊ธฐ
SELECT ID, PARENT_ID, 1 AS GENERATION
FROM ECOLI_DATA
WHERE PARENT_ID IS NULL
UNION ALL
-- ๋ ๋ฒ์งธ ์ฟผ๋ฆฌ: ์์ ๋์ฅ๊ท ์ฐพ๊ธฐ
SELECT e.ID, e.PARENT_ID, g.GENERATION + 1
FROM ECOLI_DATA e
JOIN Generation g ON e.PARENT_ID = g.ID
)
WITH RECURSIVE ์ฟผ๋ฆฌ๋ ๋ถ๋ชจ์ ์์ ๊ด๊ณ๋ฅผ ์ฌ๊ท์ ์ผ๋ก ์ถ์ ํ๊ธฐ ๋๋ฌธ์ ๊ฐ ์ธ๋๋ฅผ ์ฟผ๋ฆฌํ๋ฉด์ ์์์ด ๋ ์ด์ ์์ผ๋ฉด ์์์ ์ข
๋ฃ๊ฐ ๋๋ ๊ตฌ์กฐ์ด๋ค. ์ฆ, ์์ ๋์ฅ๊ท ์ด ๋ ์ด์ ์๊ฑฐ๋ ๋ถ๋ชจ ๋์ฅ๊ท ์ ์ฐ๊ฒฐ์ด ๋์ด์ง๋ฉด ์ฟผ๋ฆฌ๊ฐ ์ข
๋ฃ๋๋ค. ๋ง์ฝ์, ์ด๋ค ๋์ฅ๊ท ์ด 5์ธ๋์์ ๋๋๋ค๋ฉด ์ต์ข
์ธ๋์ธ 5์ธ๋๊น์ง ์ถ๋ ฅ์ ํ๋ ๊ฒ์ด๋ค.
์ด์ ์ฌ๊ธฐ์ ํน์ ๊ณ์ธต์ ์กฐํํ๋ ์ผ๋ง ๋จ์๋ค.
์ฒ์์ 1์ธ๋ ์์ ์ฃผ์๋ ALIAS๋ฅผ ORACLE์์์ LEVEL ์ฒ๋ผ ์ฌ์ฉํ๋ค.
์๋ฅผ ๋ค์ด์, 3์ธ๋ ๋ฐ์ดํฐ๋ง ํํฐ๋ง ํ๊ณ ์ถ์ผ๋ฉด
`GENERATION = 3`์ด๋ผ๋ ์กฐ๊ฑด์ ์ค๋ค.
3. ์ ๋ต์ฝ๋
WITH RECURSIVE Generation AS (
-- ์ฒซ ๋ฒ์งธ ์ฟผ๋ฆฌ: ๋ถ๋ชจ ๋์ฅ๊ท (์ฒซ ๋ฒ์งธ ์ธ๋) ์ฐพ๊ธฐ
SELECT ID, PARENT_ID, 1 AS GENERATION
FROM ECOLI_DATA
WHERE PARENT_ID IS NULL
UNION ALL
-- ๋ ๋ฒ์งธ ์ฟผ๋ฆฌ: ์์ ๋์ฅ๊ท ์ฐพ๊ธฐ
SELECT e.ID, e.PARENT_ID, g.GENERATION + 1
FROM ECOLI_DATA e
JOIN Generation g ON e.PARENT_ID = g.ID
)
-- ์ธ ๋ฒ์งธ ์ฟผ๋ฆฌ: 3์ธ๋์ธ ๋ฐ์ดํฐ ์กฐํํ๊ธฐ
SELECT ID
FROM Generation
WHERE GENERATION = 3
ORDER BY ID;
`WITH RECURSIVE Generation AS (...)`
์ฌ๊ท์ CTE(Common Table Expression)๋ฅผ ์ ์
์ฒซ ๋ฒ์งธ ๋ถ๋ถ์ 1์ธ๋ ๋์ฅ๊ท ์ ์ฐพ๊ธฐ
`PARENT_ID IS NULL`๋ก ์ต์ด ๋์ฅ๊ท ์ ์ ํํ๊ธฐ
๋ ๋ฒ์งธ ๋ถ๋ถ์ ์์ ๋์ฅ๊ท ์ฐพ๊ธฐ
`e.PARENT_ID = g.ID`๋ก ๋ถ๋ชจ ๋์ฅ๊ท ๊ณผ ์์ ๋์ฅ๊ท ์ ์ฐ๊ฒฐํ๊ณ , `GENERATION + 1`์ ์ฌ์ฉํ์ฌ ์์์ด ๋ ์ด์ ์์ ๋๊น์ง ์ธ๋ ์ฐพ๊ธฐ.
`SELECT ID FROM Generation WHERE GENERATION = 3`
GENERATION = 3์ ์กฐ๊ฑด์ผ๋ก ํ์ฌ 3์ธ๋ ๋์ฅ๊ท ๋ง ํํฐ๋ง
`ORDER BY ID`
ID ๊ธฐ์ค์ผ๋ก ์ค๋ฆ์ฐจ์ ์ ๋ ฌํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ
๐ฆTMI
๋๋ ๋ธ๋ก๊ทธ/ํ๋ก๊ทธ๋๋จธ์ค์๋ ๊ท์ฐฎ์์ ์ฟผ๋ฆฌ๋ฅผ ๋ชจ๋ ๋๋ฌธ์๋ก ์์ฑ ํ๋ค. ํ์ง๋ง....
๋ง์ SQL ์์ฑ ์คํ์ผ ๊ฐ์ด๋์์ ํ
์ด๋ธ ๋ฐ ์ปฌ๋ผ ์ด๋ฆ์ ์๋ฌธ์๋ก ์์ฑํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค.
์์ฝ์ด๋ ๋๋ฌธ์๋ก ์ฐ๊ณ SQL ์ฟผ๋ฆฌ์์ ์ปฌ๋ผ ์ด๋ฆ์ด๋, ํ
์ด๋ธ๋ช
์ ์๋ฌธ์๋ก ์จ ์ฃผ๋ฉด ์ข๋ค.
์๋ฌธ์๋ ๋๋ฌธ์๋ก ๋ ์ฝ๋์์ ๋์๋ ์ ๋ค์ด ์ค๊ณ ๋ ์ฝ๊ธฐ ์ฝ๊ณ ๊น๋ํ๊ฒ ๋ณด์ธ๋ค.
์ผํ ๋๋ ํ์ฌ ํ๋ก์ ํธ๋ DB๋ณ๋ก ๋ฐฉ์นจ์ด๋ ๊ถ์ฅ ์์์ด ์๊ฒ ์ง๋ง ๊ทธ๋ฅ ํผ์ฝ๋ฉ ํ ๋๋
SQL ์์ฝ์ด๋ ๋๋ฌธ์
ํ ์ด๋ธ๋ช ๊ณผ ์ปฌ๋ผ๋ช ์ ๋ณดํต ์๋ฌธ์
์ฌ์ฉ์ ์ ์ ์ด๋ฆ (์: CTE๋ช ) ๋ฑ ์ ๋ณดํต ์ฒซ ๊ธ์๋ง ๋๋ฌธ์
์ด๋ ๊ฒ ํ๋ ์ต๊ด์ ๋ค์ด๋ฉด ๊น๋ํ๋ค.
์ฌ๊ธฐ๊น์ง ํฌ์คํ
ํ๋๋ผ ๋๋ฌด ํ๋ค์๊ณ ์ํค๋ฐฑ๊ณผ ์งํํ๋ ๊ธฐ๋ถ์ด๋ค.
์.... ๋ฌธ์ ํ๊ณ ํฌ์คํ
์๋ฃ ์กฐ์ฌ ํ๊ณ ์ค๋ช
ํ๋๋ฐ 2์๊ฐ ์์ญ
์์ผ๋ก๋ 5๋จ๊ณ ๋ฌธ์ 1๊ฐ๋ง ๋ ํฌ์คํ
ํ๊ณ SQL์ ๋น๋ถ๊ฐ ์ฌ์ด์ผ๊ฒ ๋ค.