๐Ÿ“ŒSQL JOIN & ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค๊ณ„์˜ ํ•ต์‹ฌ ๊ฐœ๋…


1. JOIN์ด๋ž€?

๋‘ ๊ฐœ ์ด์ƒ์˜ ํ…Œ์ด๋ธ”์„ ํ•˜๋‚˜๋กœ ํ•ฉ์น˜๋Š” ๋ฐฉ๋ฒ•!

๐Ÿ“Œ JOIN์„ ์œ„ํ•œ ํ•„์ˆ˜ ๊ฐœ๋…


2. ์ •๊ทœํ™” (Normalization)๋ž€?

๐Ÿ“Œ ์ •๊ทœํ™”๋Š” ๋ฐ์ดํ„ฐ ์ค‘๋ณต์„ ์ค„์ด๊ณ , ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๊ณผ์ •

๐Ÿ“Œ ์ •๊ทœํ™”์˜ ํ•ต์‹ฌ ์›์น™

  1. ๋ฐ˜๋ณต๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์—†์•ค๋‹ค!
  2. ๊ฐ ํ…Œ์ด๋ธ”์ด ํ•˜๋‚˜์˜ ์ฃผ์ œ๋ฅผ ๊ฐ€์ง„๋‹ค!
  3. ํ…Œ์ด๋ธ” ๊ฐ„ ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•ด ์ค‘๋ณต ์—†์ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค!

3. JOIN์˜ ์ข…๋ฅ˜

์ข…๋ฅ˜ ์„ค๋ช… ์˜ˆ์ œ ๋ฌธ๋ฒ•์˜ˆ์‹œ
CROSS JOIN (๊ต์ฐจ ์กฐ์ธ) ๋‘ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ์กฐํ•ฉ์„ ๋งŒ๋“ค์–ด์ค˜์š”. ๋ชจ๋“  ํ•™์ƒ๊ณผ ๋ชจ๋“  ํ•™๊ณผ๋ฅผ ๋‹ค ์ง์ง€์–ด ๋ณด์—ฌ์คŒ SELECT A.c1, B.c2 FROM TableA A CROSS JOIN TableB B;
EQUI JOIN (๋“ฑ๊ฐ€ ์กฐ์ธ) ๊ฐ™์€ ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ํ…Œ์ด๋ธ”์„ ํ•ฉ์ณ์š”. ํ•™์ƒ๊ณผ ํ•™๊ณผ ์ •๋ณด๋ฅผ ํ•™๊ณผ ๋ฒˆํ˜ธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•ฉ์นจ SELECT A.c1, B.c2 FROM TableA A INNER JOIN TableB B ON A.cn = B.cn;
NON-EQUI JOIN (๋น„๋“ฑ๊ฐ€ ์กฐ์ธ) ๊ฐ’์ด ๊ฐ™์ง€ ์•Š์•„๋„ ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๋ฐ์ดํ„ฐ๋งŒ ํ•ฉ์ณ์š”. ์ ์ˆ˜ ๋ฒ”์œ„์— ๋”ฐ๋ผ ๋“ฑ๊ธ‰์„ ๋งค๊ธธ ๋•Œ ์‚ฌ์šฉ SELECT A.c1, B.c2 FROM TableA A INNER JOIN TableB B ON A.cn > B.cn1 and A.cn < B.cn2
OUTER JOIN (์™ธ๋ถ€ ์กฐ์ธ) ํ•œ์ชฝ ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์–ด๋„ ๋ณด์—ฌ์ค˜์š”. ํ•™๊ณผ๊ฐ€ ์—†๋Š” ํ•™์ƒ๋„ ๊ฒฐ๊ณผ์— ํฌํ•จ SELECT A.c1, B.c2 FROM TableA A LEFT OUTER JOIN TableB B ON A.cn = B.cn;
SELF JOIN (์ž๊ธฐ ์กฐ์ธ) ๊ฐ™์€ ํ…Œ์ด๋ธ”์„ ์„œ๋กœ ์—ฐ๊ฒฐํ•ด์š”. ์ง์› ๋ช…๋‹จ์—์„œ ์ƒ์‚ฌ์™€ ์ง์›์„ ์—ฐ๊ฒฐ SELECT E1.name, E2.name FROM Emp E1 INNER JOIN Emp E2 ON E1.mid = E2.id;

๐Ÿš€ CROSS JOIN (๊ต์ฐจ ์กฐ์ธ) ์™„๋ฒฝ ์ดํ•ดํ•˜๊ธฐ!

๐Ÿ“Œ ์ด ๋ฌธ์„œ๋Š” ์ดˆ๋“ฑํ•™์ƒ๋„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ต์ฐจ ์กฐ์ธ(CROSS JOIN)์˜ ๊ฐœ๋…๋ถ€ํ„ฐ ์‹ฌํ™” ๋‚ด์šฉ๊นŒ์ง€ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.


1. CROSS JOIN์ด๋ž€?

๐ŸŽฏ CROSS JOIN (๊ต์ฐจ ์กฐ์ธ)์€ ๋‘ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์กฐํ•ฉ์„ ๋งŒ๋“ค์–ด ๋‚ด๋Š” JOIN ๋ฐฉ์‹!

2. CROSS JOIN ๊ฒฐ๊ณผ๋ฅผ ์‹ค์ œ ํ…Œ์ด๋ธ”๋กœ ๋ณด๊ธฐ

๐Ÿ”น ํ•™์ƒ ํ…Œ์ด๋ธ”

ํ•™์ƒ ID ์ด๋ฆ„
1 ์ฒ ์ˆ˜
2 ์˜ํฌ

๐Ÿ”น ๊ณผ๋ชฉ ํ…Œ์ด๋ธ”

๊ณผ๋ชฉ ID ๊ณผ๋ชฉ๋ช…
A ์ˆ˜ํ•™
B ์˜์–ด

๐Ÿ‘‰ CROSS JOIN์„ ์‹คํ–‰ํ•˜๋ฉด?

โžก๏ธ ๋ชจ๋“  ํ•™์ƒ๊ณผ ๋ชจ๋“  ๊ณผ๋ชฉ์ด ์กฐํ•ฉ๋ผ์„œ ์ƒˆ๋กœ์šด ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™€์š”!

ํ•™์ƒ ID ์ด๋ฆ„ ๊ณผ๋ชฉ ID ๊ณผ๋ชฉ๋ช…
1 ์ฒ ์ˆ˜ A ์ˆ˜ํ•™
1 ์ฒ ์ˆ˜ B ์˜์–ด
2 ์˜ํฌ A ์ˆ˜ํ•™
2 ์˜ํฌ B ์˜์–ด

โœ… ๋ชจ๋“  ํ•™์ƒ์ด ๋ชจ๋“  ๊ณผ๋ชฉ์„ ์ˆ˜๊ฐ•ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ ๊ฒฐ๊ณผ!

(ํ•™์ƒ 2๋ช… ร— ๊ณผ๋ชฉ 2๊ฐœ = ์ด 4๊ฐœ์˜ ์กฐํ•ฉ์ด ๋งŒ๋“ค์–ด์ง)


3. CROSS JOIN์„ ์‹คํ–‰ํ•˜๋Š” SQL ์ฝ”๋“œ

SELECT *
FROM ํ•™์ƒ, ๊ณผ๋ชฉ;

๐Ÿ“Œ FROM ์ ˆ์— ๋‘ ๊ฐœ์˜ ํ…Œ์ด๋ธ”์„ ๊ทธ๋ƒฅ ๋‚˜์—ดํ•˜๋ฉด CROSS JOIN์ด ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰๋ผ์š”!

๐Ÿ“Œ SQL ํ‘œ์ค€ ๋ฐฉ์‹์œผ๋กœ ์ž‘์„ฑํ•˜๋ฉด ์ด๋ ‡๊ฒŒ ๋ผ์š”:

SELECT *
FROM ํ•™์ƒ
CROSS JOIN ๊ณผ๋ชฉ;

โœ…cross join(์ปฌ๋Ÿผ๋ช…) ์˜ˆ์ œ

/*
	Join : ์—ฌ๋Ÿฌ๊ฐœ์˜ ํ…Œ์ด๋ธ”์—์„œ ์กฐํšŒ
*/
-- cross join : ๋‘๊ฐœ ํ…Œ์ด๋ธ”์„ ์กฐ์ธ, m*n ๊ฐœ์˜ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ๋จ. ์‚ฌ์šฉ์‹œ ์ฃผ์˜์š”๋ง
SELECT * FROM emp -- 14r, 9c
SELECT * FROM dept -- 5r, 3c
-- mariadb ๋ฐฉ์‹
SELECT * FROM emp, dept -- 14*5=70R, 9+3= 12c
-- ansi ๋ฐฉ์‹
SELECT * FROM emp CROSS JOIN dept -- 14*5=70R, 9+3=12 c
-- ์‚ฌ์›๋ฒˆํ˜ธ(emp.empno), ์‚ฌ์›๋ช…(emp.ename), ์ง์ฑ…(emp.job),
-- ๋ถ€์„œ์ฝ”๋“œ(emp.deptno), ๋ถ€์„œ๋ช…(dept.dname), cross join
-- ์ค‘๋ณต๋œ ์ปฌ๋Ÿผ์€ ํ…Œ์ด๋ธ”๋ช…์„ ํ‘œ์‹œํ•ด์•ผํ•จ
-- ์ค‘๋ณต๋œ ์ปฌ๋Ÿผ์€ ํ…Œ์ด๋ธ”๋ช…์„ ํ‘œ์‹œํ•˜์ง€ ์•Š์•„๋„ ๋จ. 
SELECT empno, eNAME '์‚ฌ์›๋ช…', job '์ง์ฑ…',  emp.deptno, dname -- ํ…Œ์ด๋ธ”๋ช…์— ๋ณ„๋ช… ์„ค์ • 
FROM emp, dept
SELECT empno, eNAME '์‚ฌ์›๋ช…', job '์ง์ฑ…',  e.deptno, dname -- ํ…Œ์ด๋ธ”๋ช…์— ๋ณ„๋ช… ์„ค์ • 
FROM emp e, dept d
SELECT e.empno, e.eNAME '์‚ฌ์›๋ช…', e.job '์ง์ฑ…',  e.deptno, d.deptno, d.dname -- ํ…Œ์ด๋ธ”๋ช…์— ๋ณ„๋ช… ์„ค์ • 
FROM emp e, dept d

4. ์–ธ์ œ CROSS JOIN์„ ์‚ฌ์šฉํ• ๊นŒ? (์‹ฌํ™” ๊ฐœ๋…)

โœ… 1) ๋ชจ๋“  ๊ฐ€๋Šฅํ•œ ์กฐํ•ฉ์„ ๋งŒ๋“ค๊ณ  ์‹ถ์„ ๋•Œ

์˜ˆ๋ฅผ ๋“ค์–ด,

โœ… 2) ๋ฐ์ดํ„ฐ ๋ถ„์„์„ ์œ„ํ•œ ๊ฒฝ์šฐ

โœ… ๊ทธ๋Ÿฌ๋‚˜ ์กฐ์‹ฌํ•ด์•ผ ํ•  ์ !

CROSS JOIN์€ ํ…Œ์ด๋ธ”์ด ํด์ˆ˜๋ก ๋ฐ์ดํ„ฐ๊ฐ€ ๊ธฐํ•˜๊ธ‰์ˆ˜์ ์œผ๋กœ ์ฆ๊ฐ€ํ•ด์š”!

๐Ÿ“Œ ๋”ฐ๋ผ์„œ, ํ•„์š”ํ•  ๋•Œ๋งŒ ์‹ ์ค‘ํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ด์š”!


6. ๋งˆ๋ฌด๋ฆฌ ๐ŸŽ‰

โœ”๏ธ CROSS JOIN์€ ๋‘ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ์กฐํ•ฉ์„ ๋งŒ๋“œ๋Š” ์กฐ์ธ

โœ”๏ธ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์กฐํ•ฉ์„ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉ

โœ”๏ธ ์กฐํ•ฉ ๊ฐœ์ˆ˜๊ฐ€ ๋งŽ์•„์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ฃผ์˜๊ฐ€ ํ•„์š”!


๐ŸŒŸ Equi Join (๋“ฑ๊ฐ€ ์กฐ์ธ) ์™„๋ฒฝ ์ดํ•ดํ•˜๊ธฐ!

๐Ÿ“Œ ์ด ๋ฌธ์„œ๋Š” ์ดˆ๋“ฑํ•™์ƒ๋„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก Equi Join์˜ ๊ฐœ๋…๋ถ€ํ„ฐ ์‹ฌํ™” ๋‚ด์šฉ๊นŒ์ง€ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.


1. Equi Join (๋“ฑ๊ฐ€ ์กฐ์ธ)์ด๋ž€?

๐ŸŽฏ Equi Join (๋“ฑ๊ฐ€ ์กฐ์ธ)์€ ๋‘ ํ…Œ์ด๋ธ”์„ ํŠน์ •ํ•œ โ€œ๊ฐ™์€ ๊ฐ’โ€์„ ๊ธฐ์ค€์œผ๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด์—์š”!

๐Ÿ’ก ์ฆ‰, โ€œ๊ณตํ†ต๋œ ๊ฐ’โ€์„ ๊ฐ€์ง„ ํ–‰๋“ค๋งŒ ์กฐํ•ฉํ•˜๋Š” JOIN ๋ฐฉ์‹์ด์—์š”.


2. ์‹ค์ œ ํ…Œ์ด๋ธ” ์˜ˆ์ œ

๐Ÿ”น ํ•™์ƒ ํ…Œ์ด๋ธ” (Student)

ํ•™์ƒ ID ์ด๋ฆ„ ๋ฐ˜ ๋ฒˆํ˜ธ
1 ์ฒ ์ˆ˜ 101
2 ์˜ํฌ 102
3 ๋ฏผ์ˆ˜ 101

๐Ÿ”น ๋ฐ˜ ํ…Œ์ด๋ธ” (Classroom)

๋ฐ˜ ๋ฒˆํ˜ธ ๋ฐ˜ ์ด๋ฆ„
101 1ํ•™๋…„ A๋ฐ˜
102 1ํ•™๋…„ B๋ฐ˜

๐Ÿ‘‰ Equi Join์„ ์‹คํ–‰ํ•˜๋ฉด?

โžก๏ธ ๋ฐ˜ ๋ฒˆํ˜ธ๊ฐ€ ๊ฐ™์€ ํ•™์ƒ๊ณผ ๋ฐ˜ ์ •๋ณด๋ฅผ ์—ฐ๊ฒฐ!

ํ•™์ƒ ID ์ด๋ฆ„ ๋ฐ˜ ๋ฒˆํ˜ธ ๋ฐ˜ ์ด๋ฆ„
1 ์ฒ ์ˆ˜ 101 1ํ•™๋…„ A๋ฐ˜
3 ๋ฏผ์ˆ˜ 101 1ํ•™๋…„ A๋ฐ˜
2 ์˜ํฌ 102 1ํ•™๋…„ B๋ฐ˜

โœ… ๊ฐ™์€ ๋ฐ˜ ๋ฒˆํ˜ธ(101, 102)๋ฅผ ๊ฐ€์ง„ ๋ฐ์ดํ„ฐ๋ผ๋ฆฌ ์—ฐ๊ฒฐ๋˜์—ˆ์–ด์š”!


3. Equi Join SQL ์ฝ”๋“œ

SELECT ํ•™์ƒ.ID, ํ•™์ƒ.์ด๋ฆ„, ํ•™์ƒ.๋ฐ˜_๋ฒˆํ˜ธ, ๋ฐ˜.๋ฐ˜_์ด๋ฆ„
FROM ํ•™์ƒ
INNER JOIN ๋ฐ˜
ON ํ•™์ƒ.๋ฐ˜_๋ฒˆํ˜ธ = ๋ฐ˜.๋ฐ˜_๋ฒˆํ˜ธ;

๐Ÿ“Œ ON ์ ˆ์—์„œ โ€œ๋ฐ˜ ๋ฒˆํ˜ธโ€๊ฐ€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์•„ ์—ฐ๊ฒฐํ•ด์š”!

โœ…equi join(์ปฌ๋Ÿผ๋ช…) ์˜ˆ์ œ

/*
	๋“ฑ๊ฐ€์กฐ์ธ : equi join
			์กฐ์ธ์ปฌ๋Ÿผ์„ ์ด์šฉํ•˜์—ฌ ํ•„์š”ํ•œ ๋ ˆ์ฝ”๋“œ๋งŒ ์กฐํšŒ.
			์กฐ์ธ์ปฌ๋Ÿผ์˜ ์กฐ๊ฑด์„ = ์ธ ๊ฒฝ์šฐ
*/
-- ์‚ฌ์›๋ฒˆํ˜ธ, ์‚ฌ์›๋ช…, ์ง์ฑ…,๋ถ€์„œ์ฝ”๋“œ, ๋ถ€์„œ๋ช… ์กฐํšŒํ•˜๊ธฐ
SELECT e.empno, e.ename, e.job, e.deptno, d.deptno, d.dname
FROM emp e, dept d
WHERE e.deptno = d.deptno

SELECT e.empno, e.ename, e.job, e.deptno, d.deptno, d.dname
FROM emp e JOIN dept d
ON e.deptno = d.deptno -- ์กฐ์ธ์ปฌ๋Ÿผ
-- ํ•™์ƒ ํ…Œ์ด๋ธ”๊ณผ ํ•™๊ณผ(MAJOR)ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•™์ƒ์ด๋ฆ„,
-- ์ „๊ณตํ•™๊ณผ๋ฒˆํ˜ธ, ์ „๊ณตํ•™๊ณผ์ด๋ฆ„ ์กฐํšŒํ•˜๊ธฐ
-- mariaDb ๋ฐฉ์‹
SELECT S.NAME, s.major1, m.name
FROM student s, major m
WHERE s.major1 = m.code

-- ansi ๋ฐฉ์‹
SELECT S.NAME, s.major1, m.name
FROM student s join major m
on s.major1 = m.code
-- ๋ฌธ์ œ
-- ํ•™์ƒํ…Œ์ด๋ธ”์—์„œ ํ•™๋ฒˆ, ์ด๋ฆ„, score ํ…Œ์ด๋ธ”์—์„œ ํ•™๋ฒˆ์—
-- ํ•ด๋‹นํ•˜๋Š” ๊ตญ์–ด, ์ˆ˜ํ•™, ์˜์–ด ์ด์  ์กฐํšŒํ•˜๊ธฐ
-- mariaDB ๋ฐฉ์‹
SELECT s.studno, s.NAME, c.kor, c.math,c.eng, (kor+math+eng)'์ด์ '
FROM student s, score c
WHERE s.studno = c.studno
ORDER BY ์ด์  desc
-- ansi ๋ฐฉ์‹
SELECT s.studno, s.NAME, c.kor, c.math,c.eng, (kor+math+eng)'์ด์ '
FROM student s join score c
on s.studno = c.studno
ORDER BY ์ด์  desc
-- ํ•™์ƒ์˜ ์ด๋ฆ„, ํ•™๊ณผ์ด๋ฆ„, ์ง€๋„๊ต์ˆ˜ ์ด๋ฆ„ ์กฐํšŒํ•˜๊ธฐ
-- mriaDB ๋ฐฉ์‹
SELECT s.`name`, m.`name`, p.`name`
FROM student s, major m, professor p
WHERE s.major1 = m.code
AND   s.profno = p.no
-- ansi ๋ฐฉ์‹
SELECT s.`name`, m.`name`, p.`name`
FROM student s join major m
on s.major1 = m.code JOIN professor p
on s.profno = p.no
-- ๋ฌธ์ œ
-- emp ํ…Œ์ด๋ธ”๊ณผ p_grade ํ…Œ์ด๋ธ”์„ ์กฐํšŒํ•˜์—ฌ, ์‚ฌ์›์˜ ์ด๋ฆ„๊ณผ, ์ง๊ธ‰
-- ํ˜„์žฌ์—ฐ๋ด‰, ํ•ด๋‹น์ง๊ธ‰์˜ ์—ฐ๋ด‰ํ•˜ํ•œ, ์—ฐ๋ด‰์ƒํ•œ ๊ธˆ์•ก ์ถœ๋ ฅํ•˜๊ธฐ
-- ์—ฐ๋ด‰์€ (๊ธ‰์—ฌ*12+๋ณด๋„ˆ์Šค)*10000์œผ๋กœ ํ•œ๋‹ค
-- mriaDB ๋ฐฉ์‹
SELECT e.ename'์‚ฌ์›์ด๋ฆ„',e.job'์ง๊ธ‰',(salary*12+ifnull(bonus,0))*10000'์—ฐ๋ด‰',p.s_pay'์—ฐ๋ด‰ํ•˜ํ•œ',p.e_pay'์—ฐ๋ด‰์ƒํ•œ'
FROM emp e, p_grade p
WHERE e.job = p.position
-- ansi ๋ฐฉ์‹
SELECT e.ename'์‚ฌ์›์ด๋ฆ„',e.job'์ง๊ธ‰',(salary*12+ifnull(bonus,0))*10000'์—ฐ๋ด‰',p.s_pay'์—ฐ๋ด‰ํ•˜ํ•œ',p.e_pay'์—ฐ๋ด‰์ƒํ•œ'
FROM emp e JOIN p_grade p
ON e.job = p.position
-- ๋ฌธ์ œ
-- ์žฅ์„ฑํƒœ ํ•™์ƒ์˜ ํ•™๋ฒˆ, ์ด๋ฆ„ ์ „๊ณตํ•™1๊ณผ ๋ฒˆํ˜ธ,
-- ์ „๊ณต1ํ•™๊ณผ ์ด๋ฆ„, ํ•™๊ณผ ์œ„์น˜ ์ถœ๋ ฅํ•˜๊ธฐ
-- student, major ํ…Œ์ด๋ธ” ์กฐ์ธํ•˜๊ธฐ
-- mriaDB ๋ฐฉ์‹
SELECT s.studno, s.`name`, s.major1, m.`name`, ifnull(m.build,"ํ•™๊ณผ์œ„์น˜์—†์Œ") 
FROM student s, major m
WHERE s.major1 = m.code
AND s.NAME = "์žฅ์„ฑํƒœ"
-- ansi ๋ฐฉ์‹
SELECT s.studno, s.`name`, s.major1, m.`name`, ifnull(m.build,"ํ•™๊ณผ์œ„์น˜์—†์Œ") 
FROM student s join major m
on s.major1 = m.code
WHERE s.NAME = "์žฅ์„ฑํƒœ"
-- ํ•™์ƒ์˜ ํ•™๋ฒˆ, ์ด๋ฆ„ scoreํ…Œ์ด๋ธ”์—์„œ ํ•™๋ฒˆ์— ํ•ด๋‹นํ•˜๋Š”
-- ์ ์ˆ˜๋ฅผ ์กฐํšŒํ•˜๊ธฐ
-- 1ํ•™๋…„ ํ•™์ƒ์˜ ์ •๋ณด ์กฐํšŒํ•˜๊ธฐ
- mariaDB
SELECT s.studno, s.name, s2.kor, s2.math, s2.eng, (kor+math+eng)'์ด์ '
FROM student s, score s2
WHERE s.studno = s2.studno
AND s.grade = 1

-- ansi ๋ฐฉ์‹
SELECT s.studno, s.name, s2.kor, s2.math, s2.eng, (kor+math+eng)'์ด์ '
FROM student s JOIN score s2
ON s.studno = s2.studno
WHERE s.grade = 1

4. Equi Join์„ ์–ธ์ œ ์‚ฌ์šฉํ• ๊นŒ์š”? (์‹ฌํ™” ๊ฐœ๋…)

๐Ÿ’ก Equi Join์€ ์ฃผ๋กœ ๋‘ ๊ฐœ์˜ ๊ด€๋ จ๋œ ํ…Œ์ด๋ธ”์„ ์—ฐ๊ฒฐํ•  ๋•Œ ์‚ฌ์šฉํ•ด์š”.

โœ… 1) ๋ฐ์ดํ„ฐ ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ์ฐพ์„ ๋•Œ

โœ… 2) ๋ฐ์ดํ„ฐ ๋ถ„์„์„ ํ•  ๋•Œ


5. Equi Join์˜ ์„ฑ๋Šฅ ์ตœ์ ํ™” (๊ธฐ์ˆ  ๋ฉด์ ‘ ๋Œ€๋น„!)

๐Ÿ’ก ๊ธฐ์ˆ  ๋ฉด์ ‘์—์„œ ์ž์ฃผ ๋‚˜์˜ค๋Š” ์งˆ๋ฌธ๋“ค!

๐ŸŽค โ€œEqui Join์„ ์‹คํ–‰ํ•  ๋•Œ ์„ฑ๋Šฅ์„ ๋†’์ด๋Š” ๋ฐฉ๋ฒ•์€?โ€

๐Ÿ‘‰ INDEX๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค!

๐ŸŽค โ€œEqui Join๊ณผ INNER JOIN์˜ ์ฐจ์ด๋Š”?โ€

๐Ÿ‘‰ Equi Join์€ INNER JOIN์˜ ํ•œ ์ข…๋ฅ˜์ž…๋‹ˆ๋‹ค!

๐ŸŽค โ€œEqui Join์„ ์‹คํ–‰ํ•  ๋•Œ ์ฃผ์˜ํ•  ์ ์€?โ€

๐Ÿ‘‰ ์ค‘๋ณต ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์œผ๋ฉด ๊ฒฐ๊ณผ ํ–‰ ์ˆ˜๊ฐ€ ๋งŽ์•„์งˆ ์ˆ˜ ์žˆ์–ด์š”!

๐ŸŽค โ€œEqui Join๊ณผ Natural Join์˜ ์ฐจ์ด์ ์€?โ€

๐Ÿ‘‰ Natural Join์€ ๊ณตํ†ต๋œ ์ปฌ๋Ÿผ๋ช…์„ ์ž๋™์œผ๋กœ ์ฐพ์•„ ์กฐ์ธํ•˜์ง€๋งŒ, Equi Join์€ ๋ช…ํ™•ํžˆ ON ์ ˆ์„ ์‚ฌ์šฉํ•ด ์—ฐ๊ฒฐํ•  ์ปฌ๋Ÿผ์„ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


6. Equi Join vs. ๋‹ค๋ฅธ JOIN ๋น„๊ต

โœ… Equi Join vs. Cross Join

๋น„๊ต ํ•ญ๋ชฉ Equi Join Cross Join
๊ฐœ๋… ๊ณตํ†ต๋œ ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ์กฐํ•ฉ ๋ชจ๋“  ๊ฐ€๋Šฅํ•œ ์กฐํ•ฉ ์ƒ์„ฑ
๋ฐ์ดํ„ฐ ์ˆ˜ ๊ณตํ†ต ๊ฐ’์ด ์žˆ๋Š” ํ–‰๋งŒ ๋‘ ํ…Œ์ด๋ธ” ํ–‰ ์ˆ˜๋ฅผ ๊ณฑํ•œ ๊ฐœ์ˆ˜
์˜ˆ์ œ ๊ฒฐ๊ณผ ํ•™์ƒ๊ณผ ๋ฐ˜ ๋ฒˆํ˜ธ๊ฐ€ ๊ฐ™์€ ๊ฒฝ์šฐ๋งŒ ์—ฐ๊ฒฐ ๋ชจ๋“  ํ•™์ƒ๊ณผ ๋ชจ๋“  ๋ฐ˜์„ ์กฐํ•ฉ
์‚ฌ์šฉ ์˜ˆ์‹œ ๊ณ ๊ฐ๊ณผ ์ฃผ๋ฌธ์„ ์—ฐ๊ฒฐ ๋ชจ๋“  ์ง์›๊ณผ ๋ชจ๋“  ํ”„๋กœ์ ํŠธ ์กฐํ•ฉ

โœ… Equi Join vs. Outer Join

๋น„๊ต ํ•ญ๋ชฉ Equi Join Outer Join
๊ฐœ๋… ๊ณตํ†ต๋œ ๊ฐ’์ด ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋งŒ ๋ฐ˜ํ™˜ ํ•œ์ชฝ์— ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์–ด๋„ ๋ฐ˜ํ™˜
NULL ํฌํ•จ ์—ฌ๋ถ€ NULL ์—†์Œ NULL ํฌํ•จ ๊ฐ€๋Šฅ
์‚ฌ์šฉ ์˜ˆ์‹œ ์ง์›๊ณผ ๋ถ€์„œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ๋งŒ ์กฐํšŒ ๋ถ€์„œ๊ฐ€ ์—†๋Š” ์ง์›๋„ ํฌํ•จ

7. ๋งˆ๋ฌด๋ฆฌ ๐ŸŽ‰

โœ”๏ธ Equi Join์€ ๊ณตํ†ต๋œ ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ๋‘ ํ…Œ์ด๋ธ”์„ ์—ฐ๊ฒฐํ•˜๋Š” JOIN ๋ฐฉ์‹!

โœ”๏ธ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” JOIN ๋ฐฉ์‹์œผ๋กœ, ์‹ค๋ฌด์—์„œ ํ•„์ˆ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋จ

โœ”๏ธ INDEX๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ฐ€๋Šฅ!

โœ”๏ธ INNER JOIN๊ณผ ๊ฐœ๋…์ด ๊ฐ™์ง€๋งŒ, ON ์กฐ๊ฑด์ด โ€œ=โ€์ธ ๊ฒฝ์šฐ๋ฅผ ์ง€์นญ!

โœ”๏ธ ๋ฉด์ ‘์—์„œ ์ž์ฃผ ์งˆ๋ฌธ๋˜๋Š” ๊ฐœ๋…์ด๋ฏ€๋กœ ์ฐจ์ด์ ๊ณผ ์ตœ์ ํ™” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‘๊ธฐ!

๐Ÿ’ก ์ด์ œ ์ง์ ‘ SQL๋กœ Equi Join์„ ์‹คํ–‰ํ•ด ๋ณด์„ธ์š”! ๐Ÿš€


๐Ÿ† ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ (Non-Equi Join)

๋น„๋“ฑ๊ฐ€ ์กฐ์ธ(Non-Equi Join)์€ ๋‘ ํ…Œ์ด๋ธ”์„ โ€œ=โ€(๋“ฑํ˜ธ) ์—†์ด ์กฐ์ธํ•˜๋Š” ๋ฐฉ์‹์ด์•ผ!

์ฆ‰, =(๊ฐ™๋‹ค) ๋Œ€์‹  <, >, <=, >=, BETWEEN, LIKE ๊ฐ™์€ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์กฐ์ธํ•˜๋Š” ๊ฑฐ์•ผ.

๐ŸŽฏ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๋Š” ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ

๐Ÿ” ํ–„๋ฒ„๊ฑฐ ํ• ์ธ ์˜ˆ์ œ ๐Ÿ”

๋งฅ๋„๋‚ ๋“œ์—์„œ ํ–„๋ฒ„๊ฑฐ๋ฅผ ํ• ์ธํ•˜๋Š” ํ–‰์‚ฌ๊ฐ€ ์žˆ์–ด!

์ด๊ฑธ ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ์œผ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์•„!

SELECT c.name, c.age, d.discount_percent
FROM customers c
JOIN discounts d
ON c.age BETWEEN d.age_min AND d.age_max;


๐ŸŽญ ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ์˜ ์ข…๋ฅ˜

์—ฐ์‚ฐ์ž ์„ค๋ช… ์˜ˆ์ œ
< ์™ผ์ชฝ ๊ฐ’์ด ์ž‘์„ ๋•Œ ์กฐ์ธ salary.salary < job.salary_range_max
> ์™ผ์ชฝ ๊ฐ’์ด ํด ๋•Œ ์กฐ์ธ student.score > grade.min_score
<= ์™ผ์ชฝ ๊ฐ’์ด ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์„ ๋•Œ ์กฐ์ธ order.date <= promo.end_date
>= ์™ผ์ชฝ ๊ฐ’์ด ํฌ๊ฑฐ๋‚˜ ๊ฐ™์„ ๋•Œ ์กฐ์ธ employee.experience >= job.min_experience
BETWEEN ๋ฒ”์œ„ ์•ˆ์— ํฌํ•จ๋  ๋•Œ ์กฐ์ธ product.price BETWEEN discount.min_price AND discount.max_price
LIKE ํŠน์ • ํŒจํ„ด๊ณผ ์ผ์น˜ํ•  ๋•Œ ์กฐ์ธ email LIKE domain.pattern

๐Ÿ”ฅ ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ ์˜ˆ์ œ

/*๋น„๋“ฑ๊ฐ€ ์กฐ์ธ : non equi join
			์กฐ์ธ ์ปฌ๋Ÿผ์˜ ์กฐ๊ฑด์ด = ์ด ์•„๋‹Œ ๊ฒฝ์šฐ, ๋ฒ”์œ„๊ฐ’์œผ๋กœ ์กฐ์ธํ•จ
*/

-- ๊ณ ๊ฐ๋ช…๊ณผ ๊ณ ๊ฐ์ด ํฌ์ธํŠธ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ƒํ’ˆ๋ช…์„ ์กฐํšŒํ•˜๊ธฐ
-- mariaDB
SELECT g.name, g.point, p.name
FROM guest `g`, pointitem `p`
WHERE g.point BETWEEN p.spoint AND p.epoint

-- ansi ๋ฐฉ์‹
SELECT g.name, g.point, p.name
FROM guest `g`join pointitem `p`
on g.point BETWEEN p.spoint AND p.epoint
-- ๊ณ ๊ฐ์€ ์ž๊ธฐ ํฌ์ธํŠธ๋ณด๋‹ค ๋‚ฎ์€ ํฌ์ธํŠธ์˜ ์ƒํ’ˆ์„ ์„ ํƒ
-- ์™ธ์žฅํ•˜๋“œ๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ๊ณ ๊ฐ์˜
-- ๊ณ ๊ฐ๋ช…๊ณผ ๊ณ ๊ฐ์ด ํฌ์ธํŠธ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ƒํ’ˆ๋ช…์„ ์กฐํšŒํ•˜๊ธฐ
-- mariaDB
SELECT g.name, g.point, p.name, p.spoint, p.epoint
FROM guest `g`, pointitem `p`
WHERE p.spoint < g.point
AND p.name = "์™ธ์žฅํ•˜๋“œ"
-- ansi ๋ฐฉ์‹
SELECT g.name, g.point, p.name, p.spoint, p.epoint
FROM guest `g`join pointitem `p`
on p.spoint < g.point
WHERE p.name = "์™ธ์žฅํ•˜๋“œ"
-- ๋‚ฎ์€ ํฌ์ธํŠธ์˜ ์ƒํ’ˆ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ• ๋•Œ, 
-- ๊ฐœ์ธ๋ณ„๋กœ ๊ฐ€์ ธ๊ฐˆ ์ˆ˜ ์žˆ๋Š” ์ƒํ’ˆ์˜ ๊ฐฏ์ˆ˜ ์กฐํšŒ
-- ์ƒํ’ˆ์˜ ๊ฐฏ์ˆ˜๋กœ  ์ •๋ ฌํ•˜๊ธฐ
-- mariaDB
SELECT g.`name`, COUNT(*)"๊ตฌ๋งค๊ฐ€๋Šฅ์ƒํ””์ˆ˜", group_concat(p.name)
FROM guest `g`, pointitem `p`
where p.spoint <= g.point
GROUP BY g.name
ORDER BY ๊ตฌ๋งค๊ฐ€๋Šฅ์ƒํ””์ˆ˜, g.name
-- ansi ๋ฐฉ์‹
SELECT g.`name`, COUNT(*)"๊ตฌ๋งค๊ฐ€๋Šฅ์ƒํ””์ˆ˜"
FROM guest `g`join pointitem `p`
on p.spoint <= g.point
GROUP BY g.name

-- ์ƒํ’ˆ์˜ ๊ฐ์ˆ˜๊ฐ€ 2๊ฐœ ์ด์ƒ
-- mariaDB
SELECT g.`name`, COUNT(*)"๊ตฌ๋งค๊ฐ€๋Šฅ์ƒํ””์ˆ˜", group_concat(p.name)
FROM guest `g`join pointitem `p`
where p.spoint <= g.point
GROUP BY g.name
having COUNT(*)>=2
ORDER BY ๊ตฌ๋งค๊ฐ€๋Šฅ์ƒํ””์ˆ˜, g.name
-- ansi ๋ฐฉ์‹
SELECT g.`name`, COUNT(*)"๊ตฌ๋งค๊ฐ€๋Šฅ์ƒํ””์ˆ˜", group_concat(p.name)
FROM guest `g`join pointitem `p`
on p.spoint <= g.point
GROUP BY g.name
having COUNT(*)>=2
ORDER BY ๊ตฌ๋งค๊ฐ€๋Šฅ์ƒํ””์ˆ˜, g.name
-- ํ•™์ƒ์˜ ํ•™๋ฒˆ, ์ด๋ฆ„, ๊ตญ์–ด, ์ˆ˜ํ•™, ์˜์–ด, ์ด์ , ํ‰๊ท 
-- ํ•™์  ์ถœ๋ ฅํ•˜๊ธฐ
-- ํ‰๊ท ์€ ๋ฐ˜์˜ฌ๋ฆผํ•˜์—ฌ ์ •์ˆ˜๋กœ ํ‘œํ˜„ํ•˜๊ธฐ
-- mariaDB
SELECT s1.studno, s1.`name`, s2.kor, s2.math, s2.eng, (kor+math+eng), ROUND((kor+math+eng)/3)์ด์ ํ‰๊ท , s3.grade
FROM student s1, score s2, scorebase s3
WHERE s1.studno = s2.studno
AND ROUND((kor+math+eng)/3) BETWEEN s3.min_point AND s3.max_point
ORDER BY s3.grade

-- ansi ๋ฐฉ์‹
SELECT s1.studno, s1.`name`, s2.kor, s2.math, s2.eng, (kor+math+eng), ROUND((kor+math+eng)/3)์ด์ ํ‰๊ท , s3.grade
FROM student s1 join score s2
ON s1.studno = s2.studno join scorebase s3
ON ROUND((kor+math+eng)/3) BETWEEN s3.min_point AND s3.max_point
ORDER BY s3.grade

๐Ÿ”ฅ ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ์ด ๊ผญ ํ•„์š”ํ•œ ์ƒํ™ฉ 3๊ฐ€์ง€

1๏ธโƒฃ ๊ธ‰์—ฌ(Salary) ํ…Œ์ด๋ธ”๊ณผ ๋“ฑ๊ธ‰(Grade) ํ…Œ์ด๋ธ”์„ ๋งค์นญํ•  ๋•Œ

SELECT e.name, e.salary, g.grade
FROM employees e
JOIN salary_grades g
ON e.salary BETWEEN g.min_salary AND g.max_salary;

๐Ÿ”น ์ง์›์˜ ๊ธ‰์—ฌ(salary)๊ฐ€ ๊ฐ ๊ธ‰์—ฌ ๋“ฑ๊ธ‰(min_salary ~ max_salary)์— ํ•ด๋‹นํ•˜๋Š”์ง€๋ฅผ ์ฐพ์Œ!

๐Ÿ”น =์ด ์•„๋‹ˆ๋ผ ๋ฒ”์œ„ ๋น„๊ต(BETWEEN)๋ฅผ ์‚ฌ์šฉ โ†’ ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ!


2๏ธโƒฃ ์‹œํ—˜ ์ ์ˆ˜(Score)์— ๋”ฐ๋ฅธ ์„ฑ์ (Grade) ๋งค์นญ

SELECT s.name, s.score, g.grade
FROM students s
JOIN grades g
ON s.score BETWEEN g.min_score AND g.max_score;

๐Ÿ”น ํ•™์ƒ ์ ์ˆ˜(score)๊ฐ€ ๊ฐ ์„ฑ์ (grade)์˜ ์ ์ˆ˜ ๋ฒ”์œ„(min_score ~ max_score)์— ํฌํ•จ๋˜๋Š”์ง€ ํ™•์ธ!


3๏ธโƒฃ ํ• ์ธ ํ”„๋กœ๋ชจ์…˜(Discount) ์ ์šฉ

SELECT p.product_name, p.price, d.discount_percent
FROM products p
JOIN discounts d
ON p.price BETWEEN d.min_price AND d.max_price;

๐Ÿ”น ์ œํ’ˆ ๊ฐ€๊ฒฉ์ด ํ• ์ธ ๋ฒ”์œ„(min_price ~ max_price)์— ํฌํ•จ๋  ๋•Œ ๋งค์นญ!


๐ŸŽฏ ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ์ด ์–ด๋ ค์šด ๋ฉด์ ‘ ์งˆ๋ฌธ์— ๋‚˜์˜ฌ ํฌ์ธํŠธ

1๏ธโƒฃ ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ์ด ์ผ๋ฐ˜ ์กฐ์ธ(Equi Join)๊ณผ ๋‹ค๋ฅธ ์ ์€?

โœ… ์ผ๋ฐ˜ ์กฐ์ธ (Equi Join) โ†’ = ์—ฐ์‚ฐ์ž๋กœ ์ •ํ™•ํžˆ ๊ฐ™์€ ๊ฐ’์ผ ๋•Œ๋งŒ ์กฐ์ธ

โœ… ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ (Non-Equi Join) โ†’ >, <, BETWEEN, LIKE ๋“ฑ ๋ฒ”์œ„ ๊ธฐ๋ฐ˜ ์กฐ์ธ


2๏ธโƒฃ ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ์˜ ์„ฑ๋Šฅ ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€?

โœ… ์„ฑ๋Šฅ ๋ฌธ์ œ:

โœ… ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•:

  1. ํ•„์š”ํ•œ ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค ์ƒ์„ฑ (CREATE INDEX)

     CREATE INDEX idx_min_salary ON salary_grades(min_salary);
     CREATE INDEX idx_max_salary ON salary_grades(max_salary);
    
  2. ํŒŒํ‹ฐ์…˜ ํ…Œ์ด๋ธ” ์‚ฌ์šฉ โ†’ ๋ฐ์ดํ„ฐ ์–‘์ด ๋งŽ๋‹ค๋ฉด ๋ฒ”์œ„๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ…Œ์ด๋ธ”์„ ๋ถ„ํ• 
  3. JOIN ์ „์— WHERE ํ•„ํ„ฐ๋ฅผ ์ ์šฉํ•ด ๋ฐ์ดํ„ฐ ์ค„์ด๊ธฐ

๐ŸŽฏ ๊ฒฐ๋ก : ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ์€ ์–ธ์ œ ์จ์•ผ ํ• ๊นŒ?

โœ… ๋ฒ”์œ„๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐ์ธํ•  ๋•Œ!

โœ… ์ด์ง„(=) ๋น„๊ต๊ฐ€ ์•„๋‹Œ, ํฌ๊ฑฐ๋‚˜ ์ž‘์€ ๊ด€๊ณ„(>, <, BETWEEN`)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ!

โœ… ์‹œํ—˜ ์ ์ˆ˜ โ†’ ์„ฑ์  ๋“ฑ๊ธ‰, ๊ธ‰์—ฌ โ†’ ๊ธ‰์—ฌ ๋“ฑ๊ธ‰, ์ƒํ’ˆ ๊ฐ€๊ฒฉ โ†’ ํ• ์ธ์œจ ๋“ฑ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ์œ ์šฉ!

๐Ÿš€ ์ฆ‰, ๊ฐ’์ด โ€œ์ •ํ™•ํžˆ ์ผ์น˜โ€ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, โ€œ๋ฒ”์œ„โ€์— ๋”ฐ๋ผ ๋งค์นญํ•  ๋•Œ ๋น„๋“ฑ๊ฐ€ ์กฐ์ธ์ด ํ•„์š”ํ•˜๋‹ค! ๐Ÿš€


๐Ÿ” OUTER JOIN ์‹ฌํ™” ๊ฐœ๋… โ€“ ์ดˆ๋“ฑํ•™์ƒ๋„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒŒ!

OUTER JOIN์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฉด์ ‘์—์„œ ์ž์ฃผ ๋‚˜์˜ค๋Š” ์ฃผ์ œ ์ค‘ ํ•˜๋‚˜์˜ˆ์š”!

ํŠนํžˆ, ๊ธฐ๋ณธ์ ์ธ ๊ฐœ๋…์„ ๋„˜์–ด์„œ ์‹ฌํ™”๋œ ๋ฉด์ ‘ ์งˆ๋ฌธ์ด ๋‚˜์˜ค๋ฉด ์ •ํ™•ํ•œ ์ฐจ์ด๋ฅผ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ค๋Š˜์€ ์ดˆ๋“ฑํ•™์ƒ๋„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ์•„์ฃผ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•ด๋ณผ๊ฒŒ์š”! ๐Ÿ˜Š


๐Ÿ“Œ 1. OUTER JOIN์ด๋ž€?

๐ŸŽฏ ๋น„์œ ๋กœ ์ดํ•ดํ•˜๊ธฐ!

๐Ÿซ ํ•™๊ต์™€ ํ•™์ƒ ๋น„์œ 

์ด์ œ ํ•™์ƒ๋“ค์ด ์ˆ˜์—…์„ ๋“ฃ๋Š” ์ƒํ™ฉ์„ ์˜ˆ๋กœ ๋“ค์–ด๋ณผ๊ฒŒ์š”!

๐Ÿ‘‰ INNER JOIN์€ ์ˆ˜์—…์„ ๋“ฃ๋Š” ํ•™์ƒ๋งŒ ํฌํ•จ

๐Ÿ‘‰ OUTER JOIN์€ ์ˆ˜์—…์„ ๋“ฃ์ง€ ์•Š๋Š” ํ•™์ƒ๋„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Œ


๐Ÿ“Œ 2. OUTER JOIN ์ข…๋ฅ˜ (์‹ฌํ™” ๊ฐœ๋… ํฌํ•จ!)

OUTER JOIN์€ ํฌ๊ฒŒ 3๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ์–ด์š”!

JOIN ์ข…๋ฅ˜ ํฌํ•จํ•˜๋Š” ๋ฐ์ดํ„ฐ
LEFT OUTER JOIN ์™ผ์ชฝ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ + ์˜ค๋ฅธ์ชฝ ํ…Œ์ด๋ธ”์—์„œ ์ผ์น˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ
RIGHT OUTER JOIN ์˜ค๋ฅธ์ชฝ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ + ์™ผ์ชฝ ํ…Œ์ด๋ธ”์—์„œ ์ผ์น˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ
FULL OUTER JOIN ์–‘์ชฝ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ (์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ ํ•ฉ์น˜๊ณ , ์—†๋Š” ๊ฒฝ์šฐ NULL)

๐ŸŽฏ ๋น„์œ ๋กœ ์ดํ•ดํ•˜๊ธฐ!

์˜ˆ์ œ ๋ฐ์ดํ„ฐ

๐Ÿ“ ํ•™์ƒ ๋ช…๋‹จ (students ํ…Œ์ด๋ธ”)

student_id name
1 ์ฒ ์ˆ˜
2 ์˜ํฌ
3 ๋ฏผ์ˆ˜

๐Ÿ“– ์ˆ˜์—… ์ •๋ณด (subjects ํ…Œ์ด๋ธ”)

student_id subject
1 ์ˆ˜ํ•™
2 ๊ณผํ•™

โœ… 1) LEFT OUTER JOIN (์™ผ์ชฝ ํ…Œ์ด๋ธ”์„ ๊ธฐ์ค€์œผ๋กœ ์œ ์ง€!)

SELECT s.student_id, s.name, sub.subject
FROM students s
LEFT OUTER JOIN subjects sub ON s.student_id = sub.student_id;

๊ฒฐ๊ณผ:

student_id name subject
1 ์ฒ ์ˆ˜ ์ˆ˜ํ•™
2 ์˜ํฌ ๊ณผํ•™
3 ๋ฏผ์ˆ˜ NULL

๐Ÿš€ ์„ค๋ช…:

-- ํ•™์ƒ์˜ ํ•™๋ฒˆ, ์ด๋ฆ„๊ณผ ์ง€๋„๊ต์ˆ˜์ด๋ฆ„ ์ถœ๋ ฅํ•˜๊ธฐ
-- ์ง€๋„๊ต์ˆ˜๊ฐ€ ์—†๋Š” ํ•™์ƒ๋„ ์กฐํšŒ๋„๋„๋ก ํ•˜๊ณ ,
-- ์ง€๋„๊ต์ˆ˜๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ์ง€๋„๊ต์ˆ˜ ์—†์Œ ์ถœ๋ ฅํ•˜๊ธฐ
SELECT s.name, ifnull(p.`name`,"์ง€๋„๊ต์ˆ˜ ์—†์Œ")
FROM student s LEFt OUTER join professor p
on s.profno = p.no

-- --------------------
-- ์˜ค๋ผํด ๊ตฌํ˜„ ๋ฐฉ์‹
-- --------------------
-- LEFT OUTER join
SELECT s.studno, IFNULL(s.`name`,"์ง€๋„ํ•™์ƒ์—†์Œ"), p.name
FROM student s, professor p
where s.profno = p.no(+)  -- ์™ผ์ชฝ์˜ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ์กฐํšŒ

โœ… 2) RIGHT OUTER JOIN (์˜ค๋ฅธ์ชฝ ํ…Œ์ด๋ธ”์„ ๊ธฐ์ค€์œผ๋กœ ์œ ์ง€!)

SELECT s.student_id, s.name, sub.subject
FROM students s
RIGHT OUTER JOIN subjects sub ON s.student_id = sub.student_id;

๊ฒฐ๊ณผ:

student_id name subject
1 ์ฒ ์ˆ˜ ์ˆ˜ํ•™
2 ์˜ํฌ ๊ณผํ•™

๐Ÿš€ ์„ค๋ช…:

-- ํ•™์ƒ์˜ ํ•™๋ฒˆ, ์ด๋ฆ„๊ณผ ์ง€๋„๊ต์ˆ˜์ด๋ฆ„ ์กฐํšŒํ•˜๊ธฐ
-- ์ง€๋„ํ•™์ƒ์ด ์—†๋Š” ๊ต์ˆ˜๋„ ์กฐํšŒ๋˜๋„๋ก ํ•˜์ž
-- ์ง€๋„ ํ•™์ƒ์ด ์—†์œผ๋ฉด ์ง€๋„ํ•™์ƒ ์—†์Œ ๋‚ด์šฉ ์ถœ๋ ฅํ•˜๊ธฐ

SELECT s.studno, IFNULL(s.`name`,"์ง€๋„ํ•™์ƒ์—†์Œ"), p.name
FROM student s right OUTER join professor p
on s.profno = p.no

-- --------------------
-- ์˜ค๋ผํด ๊ตฌํ˜„ ๋ฐฉ์‹
-- --------------------
-- right outer join
SELECT s.studno, IFNULL(s.`name`,"์ง€๋„ํ•™์ƒ์—†์Œ"), p.name
FROM student s, professor p
where s.profno(+) = p.no  -- ์˜ค๋ฅธ์ชฝ์˜ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ์กฐํšŒ

โœ… 3) FULL OUTER JOIN (์–‘์ชฝ ํ…Œ์ด๋ธ” ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์œ ์ง€!)

SELECT s.student_id, s.name, sub.subject
FROM students s
FULL OUTER JOIN subjects sub ON s.student_id = sub.student_id;

๊ฒฐ๊ณผ:

student_id name subject
1 ์ฒ ์ˆ˜ ์ˆ˜ํ•™
2 ์˜ํฌ ๊ณผํ•™
3 ๋ฏผ์ˆ˜ NULL

๐Ÿš€ ์„ค๋ช…:

-- full outer join : union์œผ๋กœ ๊ตฌํ˜„
-- ํ•™์ƒ์˜ ์ด๋ฆ„, ์ง€๋„๊ต์ˆ˜ ์ด๋ฆ„์„ ์กฐํšŒํ•˜๊ธฐ
-- ์ง€๋„๊ต์ˆ˜๊ฐ€ ์—†๋Š” ํ•™์ƒ์ •๋ณด์™€, ์ง€๋„ํ•™์ƒ์ด ์—†๋Š” ๊ต์ˆ˜์ •๋ณด๋„
-- ์กฐํšŒํ•˜๊ธฐ
SELECT s.`name`, p.name
FROM student s LEFT join professor p 
on s.profno = p.no
UNION
SELECT s.`name`, p.name
FROM student s right join professor p 
on s.profno = p.no
-- ๋ฌธ์ œ 
-- emp, p_grade ํ…Œ์ด๋ธ”์„ ์กฐ์ธํ•˜์—ฌ
-- ์‚ฌ์›์ด๋ฆ„, ์ง๊ธ‰, ํ˜„์žฌ์—ฐ๋ด‰, ํ•ด๋‹น์ง๊ธ‰์˜ ์—ฐ๋ด‰ํ•˜ํ•œ, ์—ฐ๋ด‰์ƒํ•œ ์กฐํšŒํ•˜๊ธฐ
-- ์—ฐ๋ด‰ : (๊ธ‰์—ฌ*12+๋ณด๋„ˆ์Šค)*10000. ๋ณด๋„ˆ์Šค๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ 0์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ
-- ๋‹จ ๋ชจ๋“  ์‚ฌ์›์„ ์ถœ๋ ฅํ•˜๊ธฐ
SELECT e.ename, e.job, (salary*12+IFNULL(bonus,0))*10000 ์—ฐ๋ด‰,
p.s_pay ์—ฐ๋ด‰ํ•˜ํ•œ, p.e_pay ์—ฐ๋ด‰์ƒํ•œ
FROM emp e left join p_grade p
ON e.job = p.position
union
SELECT e.ename, e.job, (salary*12+IFNULL(bonus,0))*10000 ์—ฐ๋ด‰,
p.s_pay ์—ฐ๋ด‰ํ•˜ํ•œ, p.e_pay ์—ฐ๋ด‰์ƒํ•œ
FROM emp e right join p_grade p
ON e.job = p.position

๐Ÿ“š FULL OUTER JOIN์œผ๋กœ ๋ณด๋Š” ์ง‘ํ•ฉ ์—ฐ์‚ฐ์ž ๊ฐœ๋…

๐Ÿ› ๏ธ ์‚ฌ์šฉ๋ฒ• ๋ฐ ์˜ˆ์ œ

1. UNION

UNION ์—ฐ์‚ฐ์ž๋Š” ๋‘ ๊ฐœ์˜ SELECT ๋ฌธ์˜ ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์น˜๋ฉฐ, ์ค‘๋ณต๋œ ํ–‰์€ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ œ:

SELECT employee_id, job_id FROM employees
UNION
SELECT employee_id, job_id FROM job_history;

์œ„ ์˜ˆ์ œ๋Š” employees ํ…Œ์ด๋ธ”๊ณผ job_history ํ…Œ์ด๋ธ”์—์„œ employee_id์™€ job_id๋ฅผ ๊ฐ€์ ธ์™€ ์ค‘๋ณต์„ ์ œ๊ฑฐํ•œ ํ›„ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค

2. UNION ALL

UNION ALL ์—ฐ์‚ฐ์ž๋Š” ๋‘ ๊ฐœ์˜ SELECT ๋ฌธ์˜ ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์น˜๋ฉฐ, ์ค‘๋ณต๋œ ํ–‰๋„ ๋ชจ๋‘ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

SELECT employee_id, job_id FROM employees
UNION ALL
SELECT employee_id, job_id FROM job_history;

์ด ์˜ˆ์ œ๋Š” employees ํ…Œ์ด๋ธ”๊ณผ job_history ํ…Œ์ด๋ธ”์—์„œ employee_id์™€ job_id๋ฅผ ๊ฐ€์ ธ์™€ ์ค‘๋ณต์„ ํฌํ•จํ•˜์—ฌ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค.

3. INTERSECT

INTERSECT ์—ฐ์‚ฐ์ž๋Š” ๋‘ ๊ฐœ์˜ SELECT ๋ฌธ์˜ ๊ณตํ†ต๋œ ํ–‰๋งŒ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ œ:

SELECT employee_id, job_id FROM employees
INTERSECT
SELECT employee_id, job_id FROM job_history;

์ด ์˜ˆ์ œ๋Š” employees ํ…Œ์ด๋ธ”๊ณผ job_history ํ…Œ์ด๋ธ”์—์„œ employee_id์™€ job_id๊ฐ€ ๋ชจ๋‘ ์ผ์น˜ํ•˜๋Š” ํ–‰์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

4. EXCEPT

EXCEPT ์—ฐ์‚ฐ์ž๋Š” ์ฒซ ๋ฒˆ์งธ SELECT ๋ฌธ์˜ ๊ฒฐ๊ณผ์—์„œ ๋‘ ๋ฒˆ์งธ SELECT ๋ฌธ์˜ ๊ฒฐ๊ณผ๋ฅผ ์ œ์™ธํ•œ ํ–‰์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ œ:

SELECT employee_id, job_id FROM employees
EXCEPT
SELECT employee_id, job_id FROM job_history;

์ด ์˜ˆ์ œ๋Š” employees ํ…Œ์ด๋ธ”์—๋Š” ์กด์žฌํ•˜์ง€๋งŒ job_history ํ…Œ์ด๋ธ”์—๋Š” ์กด์žฌํ•˜์ง€ ์•Š๋Š” employee_id์™€ job_id ์กฐํ•ฉ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ

์˜ˆ์ œ:

SELECT employee_id, job_id FROM employees
UNION
SELECT employee_id, job_id FROM job_history
ORDER BY employee_id;

๐Ÿ“ ์ •๋ฆฌ


๐Ÿ“Œ 3. ์‹ฌํ™” ๊ฐœ๋…

โ“ Q1: OUTER JOIN์„ ์‚ฌ์šฉํ•  ๋•Œ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฐฉ๋ฒ•์€?

๐Ÿ‘‰ ๋‹ต๋ณ€:


โ“ Q2: LEFT JOIN๊ณผ NOT EXISTS์˜ ์ฐจ์ด๋Š”?

๐Ÿ‘‰ ๋‹ต๋ณ€:

LEFT JOIN์„ ์‚ฌ์šฉํ•  ๋•Œ NULL์„ ํ•„ํ„ฐ๋งํ•˜์—ฌ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Œ.

ํ•˜์ง€๋งŒ NOT EXISTS๋ฅผ ์“ฐ๋Š” ๊ฒŒ ๋” ์„ฑ๋Šฅ์ด ์ข‹์„ ์ˆ˜๋„ ์žˆ์Œ.

-- LEFT JOIN์„ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ
SELECT s.student_id, s.name
FROM students s
LEFT JOIN subjects sub ON s.student_id = sub.student_id
WHERE sub.subject IS NULL;

-- NOT EXISTS๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ
SELECT s.student_id, s.name
FROM students s
WHERE NOT EXISTS (
    SELECT 1 FROM subjects sub WHERE s.student_id = sub.student_id
);

โœ… ์ผ๋ฐ˜์ ์œผ๋กœ NOT EXISTS๊ฐ€ ์„ฑ๋Šฅ์ด ๋” ์ข‹์„ ์ˆ˜ ์žˆ์Œ!


โ“ Q3: FULL OUTER JOIN์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š” DB์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ํ• ๊นŒ?

๐Ÿ‘‰ ๋‹ต๋ณ€:

MySQL ๊ฐ™์€ ์ผ๋ถ€ DB๋Š” FULL OUTER JOIN์„ ์ง€์›ํ•˜์ง€ ์•Š์Œ.

์ด ๊ฒฝ์šฐ LEFT OUTER JOIN๊ณผ RIGHT OUTER JOIN์„ UNION์œผ๋กœ ๊ฒฐํ•ฉํ•˜๋ฉด ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Œ.

SELECT s.student_id, s.name, sub.subject
FROM students s
LEFT JOIN subjects sub ON s.student_id = sub.student_id
UNION
SELECT s.student_id, s.name, sub.subject
FROM students s
RIGHT JOIN subjects sub ON s.student_id = sub.student_id;

๐Ÿ“Œ 4. OUTER JOIN ์ตœ์ข… ์š”์•ฝ!

โœ… ๊ธฐ๋ณธ ๊ฐœ๋…

โœ… ์‹ฌํ™” ๊ฐœ๋… (๋ฉด์ ‘ ๋Œ€๋น„)


๐Ÿ† SELF JOIN ์‹ฌํ™” ๊ฐœ๋…

๐Ÿš€ 1. SELF JOIN์ด ๋ญ”๊ฐ€์š”?

SELF JOIN(์ž๊ธฐ ์กฐ์ธ)์ด๋ž€ ํ•˜๋‚˜์˜ ํ…Œ์ด๋ธ”์„ ์Šค์Šค๋กœ์™€ JOIN(๊ฒฐํ•ฉ)ํ•˜๋Š” ๊ฑฐ์˜ˆ์š”!

์‰ฝ๊ฒŒ ๋งํ•ด, ํ•œ ํ…Œ์ด๋ธ”์„ ๋‘ ๊ฐœ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฑฐ์ฃ .

๐Ÿ”น ์™œ SELF JOIN์„ ์‚ฌ์šฉํ• ๊นŒ์š”?


๐ŸŽฏ 2. SELF JOIN ๊ธฐ๋ณธ ๊ฐœ๋… (๊ฐ€์กฑ ๊ด€๊ณ„ ์˜ˆ์ œ)

์šฐ๋ฆฌ๊ฐ€ ๊ฐ€์กฑ ๊ด€๊ณ„๋ฅผ ์ €์žฅํ•˜๋Š” family ํ…Œ์ด๋ธ”์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณผ๊ฒŒ์š”.

id name parent_id
1 ์ฒ ์ˆ˜ NULL
2 ์˜ํฌ 1
3 ๋ฏผ์ˆ˜ 1
4 ์ง€์ˆ˜ 2

๐Ÿ“Œ ์ด ์˜๋ฏธ๋Š”?


๐Ÿ”ฅ 3. SELF JOIN์„ ํ™œ์šฉํ•ด ๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„ ์ฐพ๊ธฐ!

์ด์ œ ๋ถ€๋ชจ์™€ ์ž์‹์˜ ์ด๋ฆ„์„ ํ•จ๊ป˜ ์ถœ๋ ฅํ•ด๋ณผ๊นŒ์š”?

SELECT
    p.name AS ๋ถ€๋ชจ์ด๋ฆ„,
    c.name AS ์ž์‹์ด๋ฆ„
FROM family AS p
JOIN family AS c ON p.id = c.parent_id;

๐Ÿ“Œ ์ด SQL์ด ํ•˜๋Š” ์ผ

  1. family ํ…Œ์ด๋ธ”์„ ๋‘ ๋ฒˆ ์‚ฌ์šฉ (p: ๋ถ€๋ชจ ํ…Œ์ด๋ธ”, c: ์ž์‹ ํ…Œ์ด๋ธ”)
  2. p.id = c.parent_id ์กฐ๊ฑด์„ ํ†ตํ•ด ๋ถ€๋ชจ์™€ ์ž์‹์„ ์—ฐ๊ฒฐ
  3. ๋ถ€๋ชจ์˜ ์ด๋ฆ„๊ณผ ์ž์‹์˜ ์ด๋ฆ„์„ ์ถœ๋ ฅ

๐Ÿ”Ž ๊ฒฐ๊ณผ

๋ถ€๋ชจ์ด๋ฆ„ ์ž์‹์ด๋ฆ„
์ฒ ์ˆ˜ ์˜ํฌ
์ฒ ์ˆ˜ ๋ฏผ์ˆ˜
์˜ํฌ ์ง€์ˆ˜

๐Ÿ’ก ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด


๐Ÿ—๏ธ 4. ๊ณ ๊ธ‰ SELF JOIN โ€“ ์กฐ์ง๋„ ๋ถ„์„

SELF JOIN์€ ํšŒ์‚ฌ ์กฐ์ง๋„๋ฅผ ๋ถ„์„ํ•  ๋•Œ๋„ ๋งŽ์ด ์‚ฌ์šฉ๋ผ์š”.

๐Ÿ“Œ ์˜ˆ์ œ: ์ง์› & ์ƒ์‚ฌ ๊ด€๊ณ„ ์ฐพ๊ธฐ

์šฐ๋ฆฌ ํšŒ์‚ฌ์—๋Š” employees ํ…Œ์ด๋ธ”์ด ์žˆ์–ด์š”.

id ์ด๋ฆ„ manager_id
1 ์‚ฌ์žฅ NULL
2 ๋ถ€์žฅ 1
3 ๊ณผ์žฅ 2
4 ๋Œ€๋ฆฌ 3

๐Ÿ“Œ ์ด ์˜๋ฏธ๋Š”?

๐Ÿ”ฅ SQL ์ฝ”๋“œ: ์ง์›๊ณผ ์ƒ์‚ฌ ๊ด€๊ณ„ ์ถœ๋ ฅ

SELECT
    m.name AS ์ƒ์‚ฌ,
    e.name AS ์ง์›
FROM employees AS e
JOIN employees AS m ON e.manager_id = m.id;

๐Ÿ”Ž ๊ฒฐ๊ณผ

์ƒ์‚ฌ ์ง์›
์‚ฌ์žฅ ๋ถ€์žฅ
๋ถ€์žฅ ๊ณผ์žฅ
๊ณผ์žฅ ๋Œ€๋ฆฌ

๐Ÿ’ก ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด

๐Ÿ“Œ 4. ์˜ˆ์ œ

/*
 slef join : ๊ฐ™์€ ํ…Œ์ด๋ธ”์˜ ๋‹ค๋ฅธ์ปฌ๋Ÿผ๋“ค์„ ์กฐ์ธ ์ปฌ๋Ÿผ์œผ๋กœ ์‚ฌ์šฉํ•จ.
 				๋ฐ˜๋“œ์‹œ ํ…Œ์ด๋ธ”์˜ ๋ณ„๋ช…์„ ์„ค์ •ํ•ด์•ผํ•จ 
 				๋ฐ˜๋“œ์‹œ ๋ชจ๋“  ์ปฌ๋Ÿผ์— ํ…Œ์ด๋ธ”์˜ ๋ณ„๋ช…์„ ์„ค์ •ํ•ด์•ผํ•จ
*/
-- mgr : ์ƒ์‚ฌ์˜ ์‚ฌ์›๋ฒˆํ˜ธ
-- ์‚ฌ์›ํ…Œ์ด๋ธ”์—์„œ ์‚ฌ์›๋ฒˆํ˜ธ, ์ด๋ฆ„, ์ƒ์‚ฌ์˜ ์‚ฌ์›๋ฒˆํ˜ธ, ์ƒ์‚ฌ์˜์ด๋ฆ„ ์กฐํšŒํ•˜๊ธฐ
-- mariaDB
SELECT e1.empno, e1.ename, e2.empno, e2.ename 
FROM emp e1, emp e2
WHERE e1.mgr=e2.empno

-- ansi ๋ฐฉ์‹
SELECT e1.empno, e1.ename, e2.empno, e2.ename 
FROM emp e1 join emp e2
on e1.mgr=e2.empno
-- ๋ฌธ์ œ
-- major ํ…Œ์ด๋ธ”์—์„œ ํ•™๊ณผ์ฝ”๋“œ ํ•™๊ณผ๋ช… ์ƒ์œ„ํ•™๊ณผ์ฝ”๋“œ ์ƒ์œ„ํ•™๊ณผ๋ช…
-- ์กฐํšŒํ•˜๊ธฐ
-- code : ์ „๊ณตํ•™๊ณผ๋ช…
-- part : ์ƒ์œ„ํ•™๋ถ€๋ช…
-- mariaDB
SELECT m1.CODE ํ•™๊ณผ์ฝ”๋“œ, m1.NAME ํ•™๊ณผ๋ช…,
m1.part ์ƒ์œ„ํ•™๊ณผ์ฝ”๋“œ, m2.name ์ƒ์œ„ํ•™๊ณผ๋ช… 
FROM major m1, major m2
WHERE m1.part = m2.code

-- ansi ๋ฐฉ์‹
SELECT m1.CODE ํ•™๊ณผ์ฝ”๋“œ, m1.NAME ํ•™๊ณผ๋ช…,
m2.part ์ƒ์œ„ํ•™๊ณผ์ฝ”๋“œ, m2.name ์ƒ์œ„ํ•™๊ณผ๋ช… 
FROM major m1 join major m2
on m1.code = m2.part
-- ๊ต์ˆ˜๋ฒˆํ˜ธ ์ด๋ฆ„ ์ž…์‚ฌ์ผ ์ž…์‚ฌ์ผ์ด ๋น ๋ฅธ ์‚ฌ๋žŒ์„ ์กฐํšŒํ•˜๊ธฐ
-- ์ž…์‚ฌ์ผ์ด ๋น ๋ฅธ ์ˆœ์œผ๋กœ ์ •๋ ฌ
SELECT p1.no, p1.name, p1.hiredate, p2.no, p2.`name`, p2.hiredate
FROM professor p1, professor p2
WHERE p1.hiredate > p2.hiredate
ORDER BY p1.hiredate
-- ๊ต์ˆ˜๋ฒˆํ˜ธ ์ด๋ฆ„ ์ž…์‚ฌ์ผ ์ž…์‚ฌ์ผ์ด ๋น ๋ฅธ ์‚ฌ๋žŒ ์ธ์›์ˆ˜  ์กฐํšŒํ•˜๊ธฐ
-- ์ž…์‚ฌ์ผ์ด ๋น ๋ฅธ ์ˆœ ์ •๋ ฌ
-- mariaDB
SELECT p1.no, p1.name, p1.hiredate, p2.no, COUNT(*)
FROM professor p1, professor p2
where p1.hiredate > p2.hiredate
GROUP BY p1.no
ORDER BY p1.hiredate

-- ansi ๋ฐฉ์‹
SELECT p1.no, p1.name, p1.hiredate, p2.no, COUNT(*)
FROM professor p1 join professor p2
on p1.hiredate > p2.hiredate
GROUP BY p1.no
ORDER BY p1.hiredate

๐Ÿ” SELECT JOIN์—์„œ HAVING ์ ˆ์„ ์ž˜ ์“ฐ์ง€ ์•Š๋Š” ์ด์œ 

๋ณดํ†ต SELECT์—์„œ JOIN์„ ์‚ฌ์šฉํ•  ๋•Œ HAVING ์ ˆ์„ ๊ฑฐ์˜ ์•ˆ ์“ฐ๋Š” ์ด์œ ๋Š” HAVING์ด ๊ทธ๋ฃนํ™”(Aggregation) ์ดํ›„์˜ ํ•„ํ„ฐ๋ง์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด์—์š”. ์ผ๋ฐ˜์ ์ธ JOIN์—์„œ๋Š” ๊ทธ๋ฃนํ™” ์—†์ด ํ–‰(row) ๋‹จ์œ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒฐํ•ฉํ•˜๋ฏ€๋กœ HAVING์„ ์‚ฌ์šฉํ•  ์ผ์ด ๊ฑฐ์˜ ์—†์–ด์š”.


โœ… 1. WHERE vs HAVING ์ฐจ์ด์ 

WHERE๊ณผ HAVING์€ ๋ชจ๋‘ ํ•„ํ„ฐ๋ง(์กฐ๊ฑด์„ ๊ฑธ์–ด ํŠน์ • ๋ฐ์ดํ„ฐ๋งŒ ์ถœ๋ ฅ)ํ•˜๋Š” ์—ญํ• ์„ ํ•˜์ง€๋งŒ, ์ ์šฉ๋˜๋Š” ์‹œ์ ์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

ํ•„ํ„ฐ๋ง ๋ฐฉ์‹ ์ ์šฉ ์‹œ์  ์ฃผ์š” ์‚ฌ์šฉ ์˜ˆ
WHERE ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ(์กฐ์ธํ•˜๊ธฐ ์ „์— ์กฐ๊ฑด ๊ฒ€์‚ฌ) ๊ฐœ๋ณ„ ํ–‰(row)์— ๋Œ€ํ•œ ์กฐ๊ฑด ๊ฒ€์‚ฌ
HAVING ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋ฃนํ™”(GROUP BY)ํ•œ ํ›„ ๊ทธ๋ฃน(์ง‘๊ณ„๋œ ๋ฐ์ดํ„ฐ)์— ๋Œ€ํ•œ ์กฐ๊ฑด ๊ฒ€์‚ฌ

โœ… 2. ์ผ๋ฐ˜์ ์ธ JOIN์—์„œ WHERE ์ ˆ์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

์ผ๋ฐ˜์ ์œผ๋กœ JOIN์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๊ฐœ๋ณ„ ํ–‰์„ ํ•„ํ„ฐ๋งํ•˜๊ธฐ ์œ„ํ•ด WHERE ์ ˆ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๐ŸŽฏ ์˜ˆ์ œ: ์ง์›๊ณผ ๋ถ€์„œ ์ •๋ณด ์กฐํšŒ (INNER JOIN)

์ง์›(employees) ํ…Œ์ด๋ธ”๊ณผ ๋ถ€์„œ(departments) ํ…Œ์ด๋ธ”์ด ์žˆ๊ณ , ํŠน์ • ๋ถ€์„œ์—์„œ ์ผํ•˜๋Š” ์ง์›๋งŒ ์กฐํšŒํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

SELECT e.name, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.id
WHERE d.department_name = 'IT';

๐Ÿ“Œ ์ด ์ฟผ๋ฆฌ๋Š”?

์ด ๊ณผ์ •์—์„œ HAVING์„ ์“ธ ์ด์œ ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค!

โ†’ HAVING์€ GROUP BY ์ดํ›„ ์ง‘๊ณ„๋œ ๋ฐ์ดํ„ฐ์—๋งŒ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.


โœ… 3. HAVING์€ ์–ธ์ œ ์‚ฌ์šฉํ• ๊นŒ? (๊ทธ๋ฃนํ™”๊ฐ€ ์žˆ์„ ๋•Œ!)

HAVING์€ ์ผ๋ฐ˜์ ์ธ JOIN์—์„œ๋Š” ์•ˆ ์“ฐ์ด์ง€๋งŒ, GROUP BY์™€ ํ•จ๊ป˜ ์“ฐ์ผ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

๐ŸŽฏ ์˜ˆ์ œ: ๋ถ€์„œ๋ณ„ ์ง์› ์ˆ˜๊ฐ€ 5๋ช… ์ด์ƒ์ธ ๋ถ€์„œ๋งŒ ์กฐํšŒ

SELECT d.department_name, COUNT(e.id) AS ์ง์›์ˆ˜
FROM employees e
JOIN departments d ON e.department_id = d.id
GROUP BY d.department_name
HAVING COUNT(e.id) >= 5;

๐Ÿ“Œ ์—ฌ๊ธฐ์„œ HAVING์„ ์“ฐ๋Š” ์ด์œ ?

๐Ÿ’ก WHERE ๋Œ€์‹  HAVING์„ ์“ฐ๋Š” ์ด์œ ?


โœ… 4. ๊ฒฐ๋ก : SELECT JOIN์—์„œ HAVING์„ ์•ˆ ์“ฐ๋Š” ์ด์œ 

1๏ธโƒฃ JOIN์€ ๋ณดํ†ต ๊ฐœ๋ณ„ ํ–‰(row) ๋‹จ์œ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒฐํ•ฉํ•˜๋ฏ€๋กœ, ํ•„ํ„ฐ๋งํ•  ๋•Œ๋Š” WHERE ์ ˆ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ถฉ๋ถ„ํ•˜๋‹ค.

2๏ธโƒฃ HAVING์€ GROUP BY ์ดํ›„์— ์ง‘๊ณ„๋œ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์กฐ๊ฑด์„ ๊ฑฐ๋Š” ์—ญํ• ์ด๋ผ, ์ผ๋ฐ˜์ ์ธ JOIN์—์„œ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค.

3๏ธโƒฃ JOIN + GROUP BY๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๋•Œ HAVING์„ ์“ธ ์ˆ˜ ์žˆ์Œ

SELECT d.department_name, AVG(e.salary) AS ํ‰๊ท ๊ธ‰์—ฌ
FROM employees e
JOIN departments d ON e.department_id = d.id
GROUP BY d.department_name
HAVING AVG(e.salary) >= 5000000;

๐Ÿ“Œ ์‰ฝ๊ฒŒ ์ •๋ฆฌํ•˜์ž๋ฉด?

๐Ÿ”ฅ ๋ฉด์ ‘ ๋Œ€๋น„ ํฌ์ธํŠธ:

โœ… โ€œHAVING์€ ๊ทธ๋ฃนํ™”๋œ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ํ•„ํ„ฐ๋ง์— ์‚ฌ์šฉ๋˜๋ฏ€๋กœ, ์ผ๋ฐ˜์ ์ธ SELECT JOIN์—์„œ๋Š” WHERE๊ฐ€ ๋” ์ ์ ˆํ•˜๋‹ค.โ€ ๐Ÿš€


๐Ÿ” 5. ์‹ฌํ™”: ๊ณ„์ธต ๊ตฌ์กฐ ํŠธ๋ฆฌ ์กฐํšŒ (์žฌ๊ท€ CTE ํ™œ์šฉ)

โœ… SELF JOIN์„ ๋ฐ˜๋ณตํ•˜๋ฉด ๋‚˜๋ฌด(Tree) ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”.

โœ… ํ•˜์ง€๋งŒ ๊นŠ์€ ๊ณ„์ธต(์˜ˆ: ์‚ฌ์žฅ โ†’ ๋ถ€์žฅ โ†’ ๊ณผ์žฅ โ†’ ๋Œ€๋ฆฌ โ†’ ์‚ฌ์›)์ด ๋งŽ์•„์ง€๋ฉด JOIN์ด ๋„ˆ๋ฌด ๋งŽ์•„์ง!

โœ… ๊ทธ๋ž˜์„œ ์žฌ๊ท€ CTE(Common Table Expression)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ!

๐Ÿ“Œ ์˜ˆ์ œ: ๋ชจ๋“  ์ง์›์˜ ์ƒ์‚ฌ ์ฐพ๊ธฐ (์žฌ๊ท€ CTE)

WITH RECURSIVE EmployeeHierarchy AS (
    SELECT id, name, manager_id, 1 AS level
    FROM employees
    WHERE manager_id IS NULL  -- ์ตœ์ƒ์œ„ ๊ด€๋ฆฌ์ž ์ฐพ๊ธฐ (์‚ฌ์žฅ)

    UNION ALL

    SELECT e.id, e.name, e.manager_id, eh.level + 1
    FROM employees AS e
    JOIN EmployeeHierarchy AS eh ON e.manager_id = eh.id
)
SELECT * FROM EmployeeHierarchy;

๐Ÿ”Ž ๊ฒฐ๊ณผ

id name manager_id level
1 ์‚ฌ์žฅ NULL 1
2 ๋ถ€์žฅ 1 2
3 ๊ณผ์žฅ 2 3
4 ๋Œ€๋ฆฌ 3 4

๐Ÿ’ก ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด

โœ… ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ช‡ ๋‹จ๊ณ„๋“  ์ž๋™์œผ๋กœ ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”!


๐Ÿš€ 6. SELF JOIN์„ ์ž˜ ์‚ฌ์šฉํ•˜๋ ค๋ฉด?

SELF JOIN์€ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ•  ์ ์ด ์žˆ์–ด์š”.

โš ๏ธ 1) ์„ฑ๋Šฅ ๋ฌธ์ œ ์ฃผ์˜!

โš ๏ธ 2) NULL ๊ฐ’ ์ฒ˜๋ฆฌ ์ฃผ์˜!

โš ๏ธ 3) ์ธ๋ฑ์Šค(Index) ์ตœ์ ํ™” ํ•„์š”

CREATE INDEX idx_manager ON employees(manager_id);

๐ŸŽฏ 7. ์š”์•ฝ ์ •๋ฆฌ

๊ฐœ๋… ์„ค๋ช…
SELF JOIN ๊ธฐ๋ณธ ๊ฐœ๋… ํ•œ ํ…Œ์ด๋ธ”์„ ๋‘ ๋ฒˆ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ๊ฒฐ
๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„ ์ฐพ๊ธฐ ๊ฐ€์กฑ ๊ด€๊ณ„ ํ…Œ์ด๋ธ”์—์„œ ๋ถ€๋ชจ์™€ ์ž์‹์„ ์—ฐ๊ฒฐ
์กฐ์ง๋„ ๋ถ„์„ ์ง์›-์ƒ์‚ฌ ๊ด€๊ณ„๋ฅผ SQL๋กœ ์ฐพ๊ธฐ
์žฌ๊ท€ CTE ํ™œ์šฉ JOIN์„ ๋ฐ˜๋ณตํ•˜์ง€ ์•Š๊ณ , ๊ณ„์ธต ๊ตฌ์กฐ ํŠธ๋ฆฌ ์กฐํšŒ
์„ฑ๋Šฅ ์ตœ์ ํ™” ์ธ๋ฑ์Šค ์ถ”๊ฐ€ & NULL ์ฒ˜๋ฆฌ ์‹ ๊ฒฝ ์“ฐ๊ธฐ

๐Ÿ† ๋งˆ๋ฌด๋ฆฌ

MariaDB์—์„œ SELF JOIN์€ ๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„, ์กฐ์ง๋„ ๋ถ„์„, ๊ณ„์ธต ๊ตฌ์กฐ ์ฒ˜๋ฆฌ์— ์ž์ฃผ ์‚ฌ์šฉ๋ผ์š”.

ํ•˜์ง€๋งŒ ์žฌ๊ท€ CTE๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋” ๊น”๋”ํ•˜๊ณ  ํšจ์œจ์ ์ธ ์ฟผ๋ฆฌ ์ž‘์„ฑ ๊ฐ€๋Šฅ! ๐Ÿš€


9. ๋งˆ๋ฌด๋ฆฌ ๐ŸŽ‰

โœ… ์ •๊ทœํ™”๋ฅผ ํ†ตํ•ด ํ…Œ์ด๋ธ”์„ ๋‚˜๋ˆ„๊ณ 

โœ… ๋‚ด๋ถ€ํ‚ค(PK) & ์™ธ๋ถ€ํ‚ค(FK)๋ฅผ ์‚ฌ์šฉํ•ด ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•˜๊ณ 

โœ… JOIN์„ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ํ•ฉ์ณ์š”!

๐Ÿ’ก SQL์„ ๋ฐฐ์šด๋‹ค๋ฉด JOIN์€ ๊ผญ ์•Œ์•„์•ผ ํ•ด์š”!