๋ฐ๋ณต๋ฌธ ์์กด
1. ๋ด๋ถ์ ์ผ๋ก ๋ฐ๋ณต๋ฌธ ์ฌ์ฉ
๋ฐ๋ณต๋ฌธ์ ์ต์ํ ๊ฐ๋ฐ์๋ค์ ๋ค์์ ์์์ ๊ฐ์ด ๋ ์ฝ๋์ ํ๋์ฉ ์ ๊ทผํ๊ณ ํธ์คํธ ์ธ์ด(์ ์ฐจํ ์ธ์ด)์์ ๋ฐ๋ณต ์ฒ๋ฆฌ๋ฅผ ๊ตฌํํ๋ ๊ฒฝ์ฐ๊ฐ ๊ฐํน ์์
- ์จ๋ผ์ธ ์ฒ๋ฆฌ์์ ํ๋ฉด์ ๋ช ์ธ๋ฅผ ์ถ๋ ฅํ์กฐ๊ฐ ๋ ์ฝ๋ ํ๋์ฉ ์ ๊ทผํ๋ SELECT ๊ตฌ๋ฌธ ๋ฐ๋ณต ์ฌ์ฉ
- ๋ฐฐ์น ์ฒ๋ฆฌ์์ ๋๋์ ๋ฐ์ดํฐ ์ฒ๋ฆฌํ ๋ ๋ ์ฝ๋๋ฅผ ํ๋์ฉ ํธ์คํธ ์ธ์ด์์ ์ฒ๋ฆฌํ๊ณ ํ ์ด๋ธ์ ๊ฐฑ์
๋ฐ๋ณต๊ณ์ ๊ณตํฌ
1. ๋ฐ๋ณต๋ฌธ์ ์์กดํ ์ฝ๋์ ๋จ์
- Sales: ๋งค์ถ ๊ณ์ฐํ๋ ํ ์ด๋ธ

- Sales2: ๋งค์ถ ๋ณํ๋ฅผ ๋ํ๋ด๋ var ํ๋๋ฅผ ์ถ๊ฐํ ํ ์ด๋ธ

- ์ฒ๋ฆฌ ์๊ฐ ๋น๊ต

๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ฒ๋ฆฌ ์๊ฐ: (์ฒ๋ฆฌ ํ์) * (ํ ํ์ ๊ฑธ๋ฆฌ๋ ์ฒ๋ฆฌ ์๊ฐ)
๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ์ง ์์ ๊ฒฝ์ฐ ์ฒ๋ฆฌ ์๊ฐ: SQL ํจํด์ ๋ค์ํ์ง๋ง ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๊ณ ์คํ ๊ณํ์ ๋ณ๋์ด ์๋ค๋ฉด ๋๋ถ๋ถ ์๋งํ ์ปค๋ธํ์ผ๋ก ์ฆ๊ฐํ ๊ฒ
SQL ์คํ์ ์ค๋ฒํค๋
์ ์ฒ๋ฆฌ
1. SQL ๊ตฌ๋ฌธ์ ๋คํธ์ํฌ๋ก ์ ์ก
2. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ
3. SQL ๊ตฌ๋ฌธ Parse
4 .SQL ๊ตฌ๋ฌธ์ ์คํ ๊ณํ ์์ฑ ๋๋ ํ๊ฐ
ํ์ฒ๋ฆฌ
5. ๊ฒฐ๊ณผ ์งํฉ์ ๋คํธ์ํฌ๋ก ์ ์ก
1, 5๋ฒ์ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ผ๋ก ๊ฐ์ ๋ฐ์ดํฐ์ผํฐ ๋ด๋ถ์ ๋์ผ LAN ์์ ์์ผ๋ฏ๋ก ์ค๋ฒํค๋๊ฐ ํฌ๊ฒ ๋ฐ์ํ์ง ์์
2๋ฒ์ ๊ฒฝ์ฐ ์ปค๋ฅ์ ํ์ ์ฌ์ฉํด ๋ฏธ๋ฆฌ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฐ๊ฒฐ์ ์ผ์ ์ ํ๋ณดํด ์ค๋ฒํค๋ ํฌ์ง ์์
3๋ฒ์ ๊ฒฝ์ฐ SQL Parse(๊ตฌ๋ฌธ๋ถ์) ํ ๋ DBMS๋ง๋ค ๋ฐฉ๋ฒ๊ณผ ์ข ๋ฅ๊ฐ ๋ฌ๋ผ ์ค๋ฒํค๋๊ฐ ํผ, ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ SQL๋ฌธ์ ๋ฐ์ ๋๋ง๋ค ์คํ๋์ด ์์ SQL ๋ฌธ์ ์ฌ๋ฌ๋ฒ ๋ฐ๋ณตํ ๊ฒฝ์ฐ ์ค๋ฒํค๋ ์ปค์ง
๋ณ๋ ฌ ๋ถ์ฐ์ด ํ๋ค๋ค
๋ฐ๋ณต 1ํ๋ง๋ค ์ฒ๋ฆฌ๋ฅผ ๋จ์ํํ์ฌ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ก ์ต์ ํ ๋ถ๊ฐ๋ฅ
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ฒ ์ ์ฅ์๋ ๋๋ถ๋ถ I/O ๋ถํ๋ฅผ ๋ถ์ฐํ ์ ์๊ฒ ๋์ด์์ผ๋ ๋ฐ๋ณต๋ฌธ์์ ์คํ๋๋ SQL ๊ตฌ๋ฌธ์ ๋จ์ํ๊ธฐ ๋๋ฌธ์ ํ๋น ์ ๊ทผํ๋ ๋ฐ์ดํฐ ์์ด ์ ์ด ๋ณ๋ ฌํ ํ๊ธฐ ํ๋ฆ
์ฆ, ๋ฆฌ์์ค ์ฌ์ฉ ํจ์จ์ด ์์ข์
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์งํ๋ก ์ธํ ํํ ๋ชป๋ฐ์
๋๊ท๋ชจ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๋ณต์กํ SQL ๊ตฌ๋ฌธ์ ๋น ๋ฅด๊ฒ ํ๋๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๊ฐ์ ๋๊ณ ์์ผ๋ฏ๋ก ๋จ์ ์ฒ๋ฆฌ์ ๋ฐ๋ณต์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฅ์ ์ ํ์ฉํ ์ ์์
๋ฐ๋ณต๋ฌธ ๋์ ๋ณต์กํ SQL๋ฌธ์ ์ฌ์ฉํ๋ฉด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํ๋ํ๋ค๋ฉด ๋ฐ๋ณต๋ฌธ+๋จ์ SQL๋ฌธ ์กฐํฉ๋ณด๋ค ์ฑ๋ฅ์ด ๊ฐ์ ๋ ์ ์๋ค.
2. ๋ฐ๋ณต๊ณ๋ฅผ ๋น ๋ฅด๊ฒ ๋ง๋๋ ๋ฐฉ๋ฒ
๋ฐ๋ณต๋ฌธ+๋จ์ SQL๋ฌธ -> ๋ณต์กํ SQL๋ฌธ
์ค์ ์ํฉ์์๋ ์ฌ์ฉํ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง์
๊ฐ SQL๋ฌธ์ ๋น ๋ฅด๊ฒ ์์
๋๋ถ๋ถ unique scan, index range scan์ ๋์ ๊ฐ๋จํ ๊ตฌ๋ฌธ์ด๋ INSERT ๊ตฌ๋ฌธ์ด๋ฏ๋ก ์์ ํ๋ค๊ณ ํด๋ ํ๋, ๊ณ ์ํ ๊ฐ๋ฅ์ฑ์ด ์ ํ๋จ
๋ค์คํ ์ฒ๋ฆฌ
๊ฐ์ฅ ํฌ๋ง์ ์ธ ์ ํ์ง
์ฒ์๋ถํฐ ๋ค์ค๋๋ฅผ ์ค์ ํ ์ ์๊ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ฑํ์๋ค๋ฉด ์ฝ๋ ๋ณ๊ฒฝ ์์ด ํ์ฅ ๊ฐ๋ฅ
์์๊ฐ ์ค์ํ๊ฑฐ๋ ๋ณ๋ ฌํํ์ ๋ ๋ฌผ๋ฆฌ์ ์์์ด ๋ถ์กฑํ๋ฉด ์ฌ์ฉ ๋ถ๊ฐ
์๋ฐฑ~์์ฒ๋ง๋ฒ์ ๋ฐ๋ณต์ด ๊ธฐ๋ณธ์ธ ์ผ๊ด ์ฒ๋ฆฌ์์๋ ๋ฐ๋ณต๋ฌธ ์ฌ์ฉ์ ์ง์ํ์
3. ๋ฐ๋ณต๊ณ์ ์ฅ์
์คํ ๊ณํ์ ์์ ์ฑ
์คํ ๊ณํ์ด ๋จ์ํ์ฌ ๋ณ๋ ์ํ์ด ์์
SQL ๊ตฌ๋ฌธ ๋ด๋ถ์์ ๊ฒฐํฉ์ ์ฌ์ฉํ์ง ์์๋ ๋จ -> ๊ฒฐํฉ ์๊ณ ๋ฆฌ์ฆ์ ๋ณ๊ฒฝ์ด ์์ด ์คํ ๊ณํ ๋ณ๋ ์ ์
์์ ์ฒ๋ฆฌ ์๊ฐ์ ์ ๋ฐ๋
์คํ ๊ณํ์ด ๋จ์ํ๊ณ ์ฑ๋ฅ์ด ์์ ์ ์ด๋ฏ๋ก ์์ ์ฒ๋ฆฌ ์๊ฐ์ ์ ๋ฐ๋๊ฐ ๋์์ง
๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ์ง ์์ ๊ฒฝ์ฐ ์คํ ๊ณํ์ ๋ฐ๋ผ ์ฑ๋ฅ์ด ์ฒ์ฐจ๋ง๋ณ์ด๋ฏ๋ก ์์ํ๊ธฐ ์ด๋ ค์
ํธ๋์ญ์ ์ ์ด๊ฐ ํธ๋ฆฌ
ํธ๋์ญ์ ์ ์ ๋ฐ๋ ์ ์ด ๊ฐ๋ฅ
๊ฐฑ์ ์ฒ๋ฆฌ๋ ํน์ ์ด์ ๋ก ๋ฐฐ์น๋ฅผ ์ ์ ์ค๋จํด์ผ ํ ๋ ํด๋น ์ง์ ๊ทผ์ฒ์์ ๋ค์ ์ฒ๋ฆฌ๋ฅผ ์คํํ ์ ์์
SQL์์ ๋ฐ๋ณต ํํํ๋ ๋ฐฉ๋ฒ
1. CASE ์๊ณผ ์๋์ฐ ํจ์
INSERT INTO Sales2
SELECT company, year, sale,
CASE SIGN(sale-MAX(sale) OVER (PARTITION BY company
ORDER BY year
ROWS BETWEEN 1 PRECEDING
AND 1 PRECEDING) )
WHEN 0 THEN '='
WHEN 1 THEN '+'
WHEN -1 THEN '-'
ELSE NULL END AS var
FROM Sales;
SIGN ํจ์: ์ซ์ ์๋ฃํ์ด ์์์ด๋ฉด -1, ์์์ด๋ฉด 1, 0์ด๋ฉด 0 ๋ฐํ
ROWS BETWEEN (๊ฐ์) PRECEDING AND (๊ฐ์) PRECEDING: ํ์ฌ ๋ ์ฝ๋์์ 1๊ฐ ์ด์ ๋ถํฐ 1๊ฐ์ด์ ๊น์ง์ ๋ ์ฝ๋ ๋ฒ์
ํ์ฌ ๋ ์ฝ๋์ sale - 1๊ฐ ์ด์ ์ sale(max ํจ์ ์ฒ๋ฆฌ๋ก ๊ฐ์ ํ์ฌ์ ์ง์ ๋งค์์ ๊ฐ์ ธ์ด)
์๊ด ์๋ธ์ฟผ๋ฆฌ: ์๋ธ์ฟผ๋ฆฌ ๋ด๋ถ์์ ์ธ๋ถ ์ฟผ๋ฆฌ์์ ๊ฒฐํฉ ์กฐ๊ฑด์ ์ฌ์ฉํ๊ณ , ํด๋น ๊ฒฐํฉ ํค๋ก ์๋ผ์ง ๋ถ๋ถ ์งํฉ์ ์กฐ์ํ๋ ๊ธฐ์
์ง์ , ์งํ๋ฅผ ๊ตฌํ ๋ MAX ํจ์๋ฅผ ์ฌ์ฉํ์ง๋ง ์คํ ๊ณํ ๋ณต์กํด ์ฑ๋ฅ์ ๋ฆฌ์คํฌ ๋ฐ์, 2~3๋ฒ์งธ ์ ํ๋ฅผ ๊ตฌํ๊ธฐ๋ ์ด๋ ค์
SELECT company, year, sale,
(SELECT company FROM Sales S2
WHERE S1.company=S2.company
AND year=(SELECT MAX(year)
FROM Sales S3
WHERE S1.company=S3.company
AND S1.year>S3.year)) AS pre_company,
(SELECT sale FROM Sales S2
WHERE S1.company=S2.company
AND year=(SELECT MAX(year)
FROM Sales S3
WHERE S1.company=S3.company
AND S1.year>S3.year)) AS pre_sale
FROM Sales S1;
2. ์ต๋ ๋ฐ๋ณต ํ์๊ฐ ์ ํด์ง ๊ฒฝ์ฐ

์ฐํธ๋ฒํธ '4130033'๊ณผ ๊ฐ์ฅ ๊ฐ๊น์ด ์ฐํธ๋ฒํธ๋ฅผ ์ฐพ์ ์ถ๋ ฅํ๋ ๋ฌธ์
์์ ๋ถ์ด๊ธฐ ๋ฌธ์ ๋ก ํ๊ธฐ
SELECT pcode, district_name
FROM PostalCode
WHERE CASE WHEN pcode='4130033' THEN 0
WHEN pcode LIKE '413003%' THEN 1
WHEN pcode LIKE '41300%' THEN 2
WHEN pcode LIKE '4130%' THEN 3
WHEN pcode LIKE '413%' THEN 4
WHEN pcode LIKE '41%' THEN 5
WHEN pcode LIKE '4%' THEN 6
ELSE NULL END =
(SELECT MIN(CASE WHEN pcode='4130033' THEN 0
WHEN pcode LIKE '413003%' THEN 1
WHEN pcode LIKE '41300%' THEN 2
WHEN pcode LIKE '4130%' THEN 3
WHEN pcode LIKE '413%' THEN 4
WHEN pcode LIKE '41%' THEN 5
WHEN pcode LIKE '4%' THEN 6
ELSE NULL END)
FROM PostalCode);
์์๊ฐ ๊ฐ์ฅ ๋์(RANK๊ฐ์ด ์์) ์ฐํธ๋ฒํธ๋ฅผ ์ ํ
์๋์ฐ ํจ์๋ฅผ ์ฌ์ฉํ ์ค์บ ํ์ ๊ฐ์
์์์ ์ต์๊ฐ์ ์๋ธ์ฟผ๋ฆฌ์์ ์ฐพ๋ ๊ธฐ์กด ๋ฐฉ์ -> ์๋์ฐ ํจ์ ์ฒ๋ฆฌํ์ฌ ํ ์ด๋ธ ์ค์บ ํ์ ์ค์
SELECT pcode, district_name,
FROM (SELECT pcode, district_name,
CASE WHEN pcode='4130033' THEN 0
WHEN pcode LIKE '413003%' THEN 1
WHEN pcode LIKE '41300%' THEN 2
WHEN pcode LIKE '4130%' THEN 3
WHEN pcode LIKE '413%' THEN 4
WHEN pcode LIKE '41%' THEN 5
WHEN pcode LIKE '4%' THEN 6
ELSE NULL END AS hit_code,
MIN(CASE WHEN pcode='4130033' THEN 0
WHEN pcode LIKE '413003%' THEN 1
WHEN pcode LIKE '41300%' THEN 2
WHEN pcode LIKE '4130%' THEN 3
WHEN pcode LIKE '413%' THEN 4
WHEN pcode LIKE '41%' THEN 5
WHEN pcode LIKE '4%' THEN 6
ELSE NULL END)
OVER(ORDER BY CASE WHEN pcode='4130033' THEN 0
WHEN pcode LIKE '413003%' THEN 1
WHEN pcode LIKE '41300%' THEN 2
WHEN pcode LIKE '4130%' THEN 3
WHEN pcode LIKE '413%' THEN 4
WHEN pcode LIKE '41%' THEN 5
WHEN pcode LIKE '4%' THEN 6
ELSE NULL END) AS min_code
FROM PostalCode) Foo
WHERE hit_code=min_Code;
์๋์ฐ ํจ์๋ฅผ ์ฌ์ฉํด ์ ๋ ฌํ๋ ๋น์ฉ์ด ์ถ๊ฐ๋์์ผ๋ ํ ์ด๋ธ ํฌ๊ธฐ๊ฐ ํด ๊ฒฝ์ฐ ํ ์ด๋ธ ํ ์ค์บ์ ์ค์ด๋ ํจ๊ณผ๊ฐ ๋ ํผ
3. ๋ฐ๋ณต ํ์๊ฐ ์ ํด์ง์ง ์์ ๊ฒฝ์ฐ
์ธ์ ๋ฆฌ์คํธ ๋ชจ๋ธ๊ณผ ์ฌ๊ท ์ฟผ๋ฆฌ

ํฌ์ธํฐ ์ฒด์ธ: ์ฐํธ๋ฒํธ๋ฅผ ํค๋ก ์ผ์ ๋ฐ์ดํฐ๋ฅผ ์ค์ค์ด ์ฐ๊ฒฐํ ๊ฒ
์ธ์ ๋ฆฌ์คํธ ๋ชจ๋ธ: ํฌ์ธํฐ ์ฒด์ธ์ ์ฌ์ฉํ ํ ์ด๋ธ ํ์
์ฌ๊ท ๊ณตํต ํ ์ด๋ธ ์(recursion common table expression)์ผ๋ก ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ์ฐพ์ ์ ์์
- PostgreSQL ์ฟผ๋ฆฌ
WITH RECURSIVE Explosion (name, pcode, new_pcode, depth)
AS (SELECT name, pcode, new_pcode, 1
FROM PostalHistory
WHERE name='A'
AND new_pcode IS NULL
UNION
SELECT Child.name, Child.pcode, Child.new_pcode, depth+1
FROM Explosion AS Parent, PostalHistory AS Child
WHERE Parent.pcode=Child.new_pcode
AND Parent.name=Child.name)
SELECT name, pcode, new_pcode
FROM Explosion
WHERE depth = (SELECT MAX(depth) FROM Explosion);
์ฌ๊ท ๊ณตํต ํ ์ด๋ธ ์ Explosion์ด ํฌ์ธํฐ ์ฒด์ธ์ ํ๊ณ ์ฌ๋ผ๊ฐ ๊ณผ๊ฑฐ์ ์ฃผ์๋ฅผ ์ฐพ์
์ฌ๊ท ์์ค์ด ๊ฐ์ฅ ๊น์ ๋ ์ฝ๋ -> depth ๊ฐ์ด ๊ฐ์ฅ ํฐ ๋ ์ฝ๋
์ค์ฒฉ ์งํฉ ๋ชจ๋ธ
1) ์ธ์ ๋ฆฌ์คํธ ๋ชจ๋ธ
๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ํํํ๋ ์ ํต์ ์ธ ๋ฐฉ๋ฒ
2) ์ค์ฒฉ ์งํฉ ๋ชจ๋ธ
๊ฐ ๋ ์ฝ๋์ ๋ฐ์ดํฐ๋ฅผ ์งํฉ์ผ๋ก ๋ณด๊ณ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ์งํฉ์ ์ค์ฒฉ ๊ด๊ณ๋ก ๋ํ๋
3) ๊ฒฝ๋ก ์ด๊ฑฐ ๋ชจ๋ธ
๊ฐฑ์ ์ด ๊ฑฐ์ ๋ฐ์ํ์ง ์์ ๊ฒฝ์ฐ ์ ์ฉํ ๋ฐฉ๋ฒ
์ค์ฒฉ ์งํฉ ๋ชจ๋ธ ์์
์ถ๊ฐ๋๋ ๋ ธ๋์ ์ผ์ชฝ ๋ ์ขํ(lft): (plft*2+prgt) / 3
์ถ๊ฐ๋๋ ๋ ธ๋์ ์ผ์ชฝ ๋ ์ขํ(rgt): (plft+prgt*2) / 3

๊ฐ์ฅ ๊น์ ๋ ์ฝ๋๋ฅผ ์ฐพ๊ธฐ ์ํด ๊ฐ์ฅ ๋ฐ๊นฅ์ชฝ์ ์์ ์ฐพ์ผ๋ฉด ๋จ
๊ฐ์ฅ ๋ฐ๊นฅ์ชฝ์ ์์ ๋ค๋ฅธ ์ด๋ ํ ์์๋ ํฌํจ๋์ง ์์
SELECT name, pcode
FROM PostalHistory2 PH1
WHERE name='A'
AND NOT EXISTS
(SELECT *
FROM PostalHistory2 PH2
WHERE PH2.name='A'
AND Ph1.lft>Ph2.lft);
NOT EXISTS๋ฅผ ์ฌ์ฉํด ์ผ์ชฝ ๋์ ์ขํ๊ฐ ๋ค๋ฅธ ๋ชจ๋ ์ผ์ชฝ ๋ ์ขํ๋ณด๋ค ์๋๋ก ์กฐ๊ฑด ๋ช ์
์ฌ๊ท ์ฐ์ฐ ๋์ ์ค์ฒฉ ์ฝ๋ ์ฌ์ฉ
๋ฐ์ด์ด์ค์ ๊ณต์ฃ
๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ์ฌ์ฉํ์ง ์๋ ๊ฒ์๋ ๊ฐ๊ฐ์ ์ฅ๋จ์ ์กด์ฌ
-> ์งํฉ ์งํฅ ์ฌ๊ณ ๋ฐฉ์์ด SQL์ ๊ฐ๋ ฅํ ๋๊ตฌ์ ํ๋ ๋ฐฉ๋ฒ ํ์ฉ์ ๋ฐ๋์ ํ์ํจ
'SQL > SQL ๋ ๋ฒจ์ ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [SQL ๋ ๋ฒจ์ ] 7์ฅ: ์๋ธ์ฟผ๋ฆฌ (0) | 2022.05.02 |
|---|---|
| [SQL ๋ ๋ฒจ์ ] 6์ฅ: ๊ฒฐํฉ (0) | 2022.04.25 |
| [SQL ๋ ๋ฒจ์ ] 4์ฅ: ์ง์ฝ๊ณผ ์๋ฅด๊ธฐ (0) | 2022.04.18 |
| [SQL ๋ ๋ฒจ์ ] 3์ฅ: SQL์ ์กฐ๊ฑด ๋ถ๊ธฐ (0) | 2022.04.11 |
| [SQL ๋ ๋ฒจ์ ] 2์ฅ: SQL ๊ธฐ์ด (0) | 2022.04.10 |
๋๊ธ