๐SQL JOIN & ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ์ ํต์ฌ ๊ฐ๋
1. JOIN์ด๋?
๋ ๊ฐ ์ด์์ ํ ์ด๋ธ์ ํ๋๋ก ํฉ์น๋ ๋ฐฉ๋ฒ!
๐ JOIN์ ์ํ ํ์ ๊ฐ๋
- ๋ด๋ถํค (Primary Key, PK): ํ ์ด๋ธ์์ ๊ณ ์ ํ ๊ฐ (์: ํ๋ฒ)
- ์ธ๋ถํค (Foreign Key, FK): ๋ค๋ฅธ ํ ์ด๋ธ์ PK๋ฅผ ์ฐธ์กฐํ๋ ๊ฐ (์: ํ์ ํ ์ด๋ธ์ ํ๊ณผ ๋ฒํธ)
2. ์ ๊ทํ (Normalization)๋?
๐ ์ ๊ทํ๋ ๋ฐ์ดํฐ ์ค๋ณต์ ์ค์ด๊ณ , ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ๋ ๊ณผ์
๐ ์ ๊ทํ์ ํต์ฌ ์์น
- ๋ฐ๋ณต๋๋ ๋ฐ์ดํฐ๋ฅผ ์์ค๋ค!
- ๊ฐ ํ ์ด๋ธ์ด ํ๋์ ์ฃผ์ ๋ฅผ ๊ฐ์ง๋ค!
- ํ ์ด๋ธ ๊ฐ ๊ด๊ณ๋ฅผ ์ค์ ํด ์ค๋ณต ์์ด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ๋ค!
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์ ํ ์ด๋ธ์ด ํด์๋ก ๋ฐ์ดํฐ๊ฐ ๊ธฐํ๊ธ์์ ์ผ๋ก ์ฆ๊ฐํด์!
- ํ์์ด 100๋ช
์ด๊ณ , ๊ณผ๋ชฉ์ด 10๊ฐ๋ผ๋ฉด?
- 100 ร 10 = 1,000๊ฐ์ ์กฐํฉ์ด ์๊ฒจ์! ๐ฒ
- ํ์์ด 10,000๋ช
์ด๊ณ , ๊ณผ๋ชฉ์ด 50๊ฐ๋ผ๋ฉด?
- 10,000 ร 50 = 500,000๊ฐ์ ์กฐํฉ ๐คฏ
๐ ๋ฐ๋ผ์, ํ์ํ ๋๋ง ์ ์คํ๊ฒ ์ฌ์ฉํด์ผ ํด์!
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์ ON ์กฐ๊ฑด์ ๊ธฐ๋ฐ์ผ๋ก ๋ ํ ์ด๋ธ์ ๋น๊ตํ๋๋ฐ, ํด๋น ์ปฌ๋ผ์ INDEX๊ฐ ์์ผ๋ฉด ๊ฒ์ ์๋๊ฐ ๋นจ๋ผ์ ธ์!
๐ค โEqui Join๊ณผ INNER JOIN์ ์ฐจ์ด๋?โ
๐ Equi Join์ INNER JOIN์ ํ ์ข ๋ฅ์ ๋๋ค!
- INNER JOIN์ โ๊ณตํต๋ ๋ฐ์ดํฐ๋ง ์ฐ๊ฒฐโํ๋ JOIN ๋ฐฉ์
- Equi 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
๊ฐ์ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด์ ์กฐ์ธํ๋ ๊ฑฐ์ผ.
๐ฏ ์ฝ๊ฒ ์ดํดํ๋ ๋น๋ฑ๊ฐ ์กฐ์ธ
๐ ํ๋ฒ๊ฑฐ ํ ์ธ ์์ ๐
๋งฅ๋๋ ๋์์ ํ๋ฒ๊ฑฐ๋ฅผ ํ ์ธํ๋ ํ์ฌ๊ฐ ์์ด!
- ๋์ด 0~5์ด์ด๋ฉด 100% ๋ฌด๋ฃ!
- ๋์ด 6~12์ด์ด๋ฉด 50% ํ ์ธ!
- ๋์ด 13~18์ด์ด๋ฉด 20% ํ ์ธ!
- ๋์ด 19์ด ์ด์์ด๋ฉด ํ ์ธ ์์!
์ด๊ฑธ ๋น๋ฑ๊ฐ ์กฐ์ธ์ผ๋ก ํํํ๋ฉด ๋ค์๊ณผ ๊ฐ์!
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;
customers
ํ ์ด๋ธ โ ๊ณ ๊ฐ ์ ๋ณด (์ด๋ฆ, ๋์ด)discounts
ํ ์ด๋ธ โ ํ ์ธ ์ ๋ณด (๋์ด ๋ฒ์, ํ ์ธ์จ)BETWEEN age_min AND 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) ํ ์ด๋ธ์ ๋งค์นญํ ๋
- ๊ธ์ฌ๊ฐ ํน์ ๊ธ์ฌ ๋ฑ๊ธ(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) ๋งค์นญ
- ํ์ ์ ์๋ฅผ ๊ธฐ์ค์ผ๋ก A, B, C, D, F ์ฑ์ ์ ๋ถ์ฌํ๋ ๊ฒฝ์ฐ
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๏ธโฃ ๋น๋ฑ๊ฐ ์กฐ์ธ์ ์ฑ๋ฅ ๋ฌธ์ ์ ํด๊ฒฐ ๋ฐฉ๋ฒ์?
โ ์ฑ๋ฅ ๋ฌธ์ :
ON
์กฐ๊ฑด์ ๋ฒ์(BETWEEN
,<
,>
)๊ฐ ๋ค์ด๊ฐ๋ฏ๋ก ์ธ๋ฑ์ค๋ฅผ ์ ํ์ฉํ์ง ๋ชปํ ์๋ ์์!- ๋ฐ์ดํฐ๊ฐ ๋ง์์ง๋ฉด ๋นํจ์จ์ ์ธ ํ ์ค์บ(Full Scan)์ด ๋ฐ์ํ ์ ์์.
โ ํด๊ฒฐ ๋ฐฉ๋ฒ:
-
ํ์ํ ์ปฌ๋ผ์ ์ธ๋ฑ์ค ์์ฑ (
CREATE INDEX
)CREATE INDEX idx_min_salary ON salary_grades(min_salary); CREATE INDEX idx_max_salary ON salary_grades(max_salary);
- ํํฐ์ ํ ์ด๋ธ ์ฌ์ฉ โ ๋ฐ์ดํฐ ์์ด ๋ง๋ค๋ฉด ๋ฒ์๋ฅผ ๊ธฐ์ค์ผ๋ก ํ ์ด๋ธ์ ๋ถํ
- JOIN ์ ์ WHERE ํํฐ๋ฅผ ์ ์ฉํด ๋ฐ์ดํฐ ์ค์ด๊ธฐ
๐ฏ ๊ฒฐ๋ก : ๋น๋ฑ๊ฐ ์กฐ์ธ์ ์ธ์ ์จ์ผ ํ ๊น?
โ ๋ฒ์๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์กฐ์ธํ ๋!
โ
์ด์ง(=) ๋น๊ต๊ฐ ์๋, ํฌ๊ฑฐ๋ ์์ ๊ด๊ณ(
>,
<,
BETWEEN`)๋ฅผ ์ฌ์ฉํ ๋!
โ ์ํ ์ ์ โ ์ฑ์ ๋ฑ๊ธ, ๊ธ์ฌ โ ๊ธ์ฌ ๋ฑ๊ธ, ์ํ ๊ฐ๊ฒฉ โ ํ ์ธ์จ ๋ฑ๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์ ์ ์ฉ!
๐ ์ฆ, ๊ฐ์ด โ์ ํํ ์ผ์นโํ๋ ๊ฒ ์๋๋ผ, โ๋ฒ์โ์ ๋ฐ๋ผ ๋งค์นญํ ๋ ๋น๋ฑ๊ฐ ์กฐ์ธ์ด ํ์ํ๋ค! ๐
๐ OUTER JOIN ์ฌํ ๊ฐ๋ โ ์ด๋ฑํ์๋ ์ดํดํ ์ ์๊ฒ!
OUTER JOIN์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฉด์ ์์ ์์ฃผ ๋์ค๋ ์ฃผ์ ์ค ํ๋์์!
ํนํ, ๊ธฐ๋ณธ์ ์ธ ๊ฐ๋ ์ ๋์ด์ ์ฌํ๋ ๋ฉด์ ์ง๋ฌธ์ด ๋์ค๋ฉด ์ ํํ ์ฐจ์ด๋ฅผ ์๊ณ ์์ด์ผ ํฉ๋๋ค.
์ค๋์ ์ด๋ฑํ์๋ ์ดํดํ ์ ์๋๋ก ์์ฃผ ์ฝ๊ฒ ์ค๋ช ํด๋ณผ๊ฒ์! ๐
๐ 1. OUTER JOIN์ด๋?
๐ฏ ๋น์ ๋ก ์ดํดํ๊ธฐ!
๐ซ ํ๊ต์ ํ์ ๋น์
students
ํ ์ด๋ธ: ํ๊ต์ ๋ฑ๋ก๋ ํ์ ๋ช ๋จsubjects
ํ ์ด๋ธ: ๊ฐ ํ์์ด ์๊ฐํ๋ ๊ณผ๋ชฉ
์ด์ ํ์๋ค์ด ์์ ์ ๋ฃ๋ ์ํฉ์ ์๋ก ๋ค์ด๋ณผ๊ฒ์!
๐ 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 |
๐ ์ค๋ช :
students
ํ ์ด๋ธ(์ผ์ชฝ)์ ๋ชจ๋ ๋ฐ์ดํฐ ์ ์งsubjects
ํ ์ด๋ธ(์ค๋ฅธ์ชฝ)์์ ์ผ์นํ๋ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ๊ฐ์ ธ์ด- ์๋ ๊ฒฝ์ฐ 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 | ์ํฌ | ๊ณผํ |
๐ ์ค๋ช :
subjects
ํ ์ด๋ธ(์ค๋ฅธ์ชฝ)์ ๋ชจ๋ ๋ฐ์ดํฐ ์ ์งstudents
ํ ์ด๋ธ(์ผ์ชฝ)์์ ์ผ์นํ๋ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ๊ฐ์ ธ์ด- ํ์ง๋ง ์ฌ๊ธฐ์๋
subjects
ํ ์ด๋ธ์ ์๋ ํ์(๋ฏผ์)์ ์์ ๋์ค์ง ์์
-- ํ์์ ํ๋ฒ, ์ด๋ฆ๊ณผ ์ง๋๊ต์์ด๋ฆ ์กฐํํ๊ธฐ
-- ์ง๋ํ์์ด ์๋ ๊ต์๋ ์กฐํ๋๋๋ก ํ์
-- ์ง๋ ํ์์ด ์์ผ๋ฉด ์ง๋ํ์ ์์ ๋ด์ฉ ์ถ๋ ฅํ๊ธฐ
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 |
๐ ์ค๋ช :
students
ํ ์ด๋ธ(์ผ์ชฝ) +subjects
ํ ์ด๋ธ(์ค๋ฅธ์ชฝ) ๋ชจ๋ ๋ฐ์ดํฐ ์ ์ง- ์ผ์นํ์ง ์๋ ๋ฐ์ดํฐ๋ NULL
LEFT OUTER JOIN
๊ณผRIGHT OUTER JOIN
์ ํฉ์น ๊ฐ๋
-- 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์ผ๋ก ๋ณด๋ ์งํฉ ์ฐ์ฐ์ ๊ฐ๋
UNION
: ๋ ๊ฐ์ SELECT ๋ฌธ์ ๊ฒฐ๊ณผ๋ฅผ ํฉ์น๋, ์ค๋ณต๋ ํ์ ์ ๊ฑฐํฉ๋๋ค.UNION ALL
: ๋ ๊ฐ์ SELECT ๋ฌธ์ ๊ฒฐ๊ณผ๋ฅผ ํฉ์น๋ฉฐ, ์ค๋ณต๋ ํ๋ ๋ชจ๋ ํฌํจํฉ๋๋ค.INTERSECT
: ๋ ๊ฐ์ SELECT ๋ฌธ์ ๊ณตํต๋ ํ๋ง ๋ฐํํฉ๋๋ค.EXCEPT
: ์ฒซ ๋ฒ์งธ SELECT ๋ฌธ์ ๊ฒฐ๊ณผ์์ ๋ ๋ฒ์งธ SELECT ๋ฌธ์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ธํ ํ์ ๋ฐํํฉ๋๋ค.
๐ ๏ธ ์ฌ์ฉ๋ฒ ๋ฐ ์์
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
์กฐํฉ์ ๋ฐํํฉ๋๋ค.
โ ๏ธ ์ฃผ์์ฌํญ
UNION
,INTERSECT
,EXCEPT
๋ฅผ ์ฌ์ฉํ ๋, ๊ฒฐํฉ๋๋ ๊ฐ SELECT ๋ฌธ์ ์ด ์์ ๋ฐ์ดํฐ ํ์ ์ด ์ผ์นํด์ผ ํฉ๋๋ค.ORDER BY
์ ์ ์ ์ฒด ๊ฒฐ๊ณผ ์งํฉ์ ๋ํด ํ ๋ฒ๋ง ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ๋ง์ง๋ง SELECT ๋ฌธ ๋ค์ ์์นํด์ผ ํฉ๋๋ค.
์์ :
SELECT employee_id, job_id FROM employees
UNION
SELECT employee_id, job_id FROM job_history
ORDER BY employee_id;
๐ ์ ๋ฆฌ
UNION
: ์ค๋ณต์ ์ ๊ฑฐํ ํฉ์งํฉ์ ๋ฐํํฉ๋๋ค.UNION ALL
: ์ค๋ณต์ ํฌํจํ ํฉ์งํฉ์ ๋ฐํํฉ๋๋ค.INTERSECT
: ๋ ๊ฒฐ๊ณผ ์งํฉ์ ๊ต์งํฉ์ ๋ฐํํฉ๋๋ค.EXCEPT
: ์ฒซ ๋ฒ์งธ ๊ฒฐ๊ณผ ์งํฉ์์ ๋ ๋ฒ์งธ ๊ฒฐ๊ณผ ์งํฉ์ ์ ์ธํ ์ฐจ์งํฉ์ ๋ฐํํฉ๋๋ค.
๐ 3. ์ฌํ ๊ฐ๋
โ Q1: OUTER JOIN์ ์ฌ์ฉํ ๋ ์ฑ๋ฅ ์ต์ ํ ๋ฐฉ๋ฒ์?
๐ ๋ต๋ณ:
OUTER JOIN
์INNER JOIN
๋ณด๋ค ์ฑ๋ฅ์ด ๋๋ฆผ- NULL ๊ฐ์ ์ฒ๋ฆฌํด์ผ ํ๋ฏ๋ก ์ธ๋ฑ์ค(index)๋ฅผ ํ์ฉํด์ผ ํจ
- ๋ถํ์ํ NULL ๋ฐ์ดํฐ๋ฅผ ์ค์ด๋ ค๋ฉด WHERE ์กฐ๊ฑด์ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์
-
์๋ฅผ ๋ค์ด, ์์ ์ ๋ฃ๋ ํ์๋ง ์กฐํํ๊ณ ์ถ๋ค๋ฉด?
SELECT s.student_id, s.name, sub.subject FROM students s LEFT OUTER JOIN subjects sub ON s.student_id = sub.student_id WHERE sub.subject IS NOT NULL;
โ 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 ์ต์ข ์์ฝ!
โ ๊ธฐ๋ณธ ๊ฐ๋
LEFT OUTER JOIN
: ์ผ์ชฝ ํ ์ด๋ธ ๊ธฐ์ค, ์ค๋ฅธ์ชฝ์์ ์ผ์นํ๋ ๋ฐ์ดํฐ ํฌํจRIGHT OUTER JOIN
: ์ค๋ฅธ์ชฝ ํ ์ด๋ธ ๊ธฐ์ค, ์ผ์ชฝ์์ ์ผ์นํ๋ ๋ฐ์ดํฐ ํฌํจFULL OUTER JOIN
: ์์ชฝ ํ ์ด๋ธ ๋ชจ๋ ๋ฐ์ดํฐ ํฌํจ
โ ์ฌํ ๊ฐ๋ (๋ฉด์ ๋๋น)
- ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํด ์ธ๋ฑ์ค ํ์ฉ & WHERE ํํฐ๋ง
NOT EXISTS
๊ฐLEFT JOIN + NULL ํํฐ๋ง
๋ณด๋ค ์ฑ๋ฅ์ด ๋์ ์ ์์FULL OUTER JOIN
์ด ์๋ DB์์๋ LEFT JOIN + RIGHT JOIN + UNION ์ฌ์ฉ
๐ 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 |
๐ ์ด ์๋ฏธ๋?
- ์ฒ ์(id=1)๋ ๋ถ๋ชจ๊ฐ ์์ (์ฆ, ์กฐ์)
- ์ํฌ(id=2)์ ๋ฏผ์(id=3)๋ ์ฒ ์(id=1)์ ์๋
- ์ง์(id=4)๋ ์ํฌ(id=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์ด ํ๋ ์ผ
family
ํ ์ด๋ธ์ ๋ ๋ฒ ์ฌ์ฉ (p: ๋ถ๋ชจ ํ ์ด๋ธ, c: ์์ ํ ์ด๋ธ)p.id = c.parent_id
์กฐ๊ฑด์ ํตํด ๋ถ๋ชจ์ ์์์ ์ฐ๊ฒฐ- ๋ถ๋ชจ์ ์ด๋ฆ๊ณผ ์์์ ์ด๋ฆ์ ์ถ๋ ฅ
๐ ๊ฒฐ๊ณผ
๋ถ๋ชจ์ด๋ฆ | ์์์ด๋ฆ |
---|---|
์ฒ ์ | ์ํฌ |
์ฒ ์ | ๋ฏผ์ |
์ํฌ | ์ง์ |
๐ก ์ฝ๊ฒ ๋งํ๋ฉด
- ์ฒ ์์ ์๋ ๋ ์ํฌ, ๋ฏผ์
- ์ํฌ์ ์๋ ๋ ์ง์
๐๏ธ 4. ๊ณ ๊ธ SELF JOIN โ ์กฐ์ง๋ ๋ถ์
SELF JOIN์ ํ์ฌ ์กฐ์ง๋๋ฅผ ๋ถ์ํ ๋๋ ๋ง์ด ์ฌ์ฉ๋ผ์.
๐ ์์ : ์ง์ & ์์ฌ ๊ด๊ณ ์ฐพ๊ธฐ
์ฐ๋ฆฌ ํ์ฌ์๋ employees
ํ
์ด๋ธ์ด ์์ด์.
id | ์ด๋ฆ | manager_id |
---|---|---|
1 | ์ฌ์ฅ | NULL |
2 | ๋ถ์ฅ | 1 |
3 | ๊ณผ์ฅ | 2 |
4 | ๋๋ฆฌ | 3 |
๐ ์ด ์๋ฏธ๋?
- ์ฌ์ฅ(id=1)์ ์์ฌ๊ฐ ์์
- ๋ถ์ฅ(id=2)์ ์์ฌ๋ ์ฌ์ฅ(id=1)
- ๊ณผ์ฅ(id=3)์ ์์ฌ๋ ๋ถ์ฅ(id=2)
- ๋๋ฆฌ(id=4)์ ์์ฌ๋ ๊ณผ์ฅ(id=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';
๐ ์ด ์ฟผ๋ฆฌ๋?
JOIN
์ ์ด์ฉํด ์ง์๊ณผ ๋ถ์ ์ ๋ณด๋ฅผ ๊ฒฐํฉWHERE
์ ์ฌ์ฉํด'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์ ์ฐ๋ ์ด์ ?
GROUP BY d.department_name
โ ๋ถ์๋ณ๋ก ์ง์ ์๋ฅผ ๊ทธ๋ฃนํCOUNT(e.id)
โ ๋ถ์๋ณ ์ง์ ์ ๊ณ์ฐHAVING COUNT(e.id) >= 5
โ ์ง์ ์๊ฐ 5๋ช ์ด์์ธ ๋ถ์๋ง ํํฐ๋ง
๐ก WHERE ๋์ HAVING์ ์ฐ๋ ์ด์ ?
COUNT(e.id) >= 5
๋ ๊ฐ๋ณ ํ์ด ์๋๋ผ ์ง๊ณ๋ ๊ฐ(๋ถ์๋ณ ์ง์ ์)์ ํํฐ๋งํ๋ ๊ฒ์ด๋ฏ๋ก,HAVING
์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
โ 4. ๊ฒฐ๋ก : SELECT JOIN์์ HAVING์ ์ ์ฐ๋ ์ด์
1๏ธโฃ JOIN์ ๋ณดํต ๊ฐ๋ณ ํ(row) ๋จ์๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฒฐํฉํ๋ฏ๋ก, ํํฐ๋งํ ๋๋ WHERE ์ ์ ์ฌ์ฉํ๋ฉด ์ถฉ๋ถํ๋ค.
2๏ธโฃ HAVING์ GROUP BY ์ดํ์ ์ง๊ณ๋ ๋ฐ์ดํฐ์ ๋ํ ์กฐ๊ฑด์ ๊ฑฐ๋ ์ญํ ์ด๋ผ, ์ผ๋ฐ์ ์ธ JOIN
์์๋ ํ์ํ์ง ์๋ค.
3๏ธโฃ JOIN + GROUP BY๋ฅผ ํจ๊ป ์ฌ์ฉํ ๋ HAVING์ ์ธ ์ ์์
- ์: ๋ถ์๋ณ ํ๊ท ๊ธ์ฌ๊ฐ 500๋ง ์ ์ด์์ธ ๋ถ์๋ง ์กฐํ
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;
๐ ์ฝ๊ฒ ์ ๋ฆฌํ์๋ฉด?
- ํ(row) ํํฐ๋ง โ WHERE ์ฌ์ฉ
- ์ง๊ณ๋ ๊ฐ(๊ทธ๋ฃนํ๋ ๋ฐ์ดํฐ) ํํฐ๋ง โ HAVING ์ฌ์ฉ
- ์ผ๋ฐ์ ์ธ
JOIN
์์๋ ๊ฐ๋ณ ํ ๋จ์๋ก ๋ฐ์ดํฐ๋ฅผ ํฉ์น๊ธฐ ๋๋ฌธ์,HAVING
์ ์ธ ํ์๊ฐ ๊ฑฐ์ ์๋ค.
๐ฅ ๋ฉด์ ๋๋น ํฌ์ธํธ:
โ โ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 |
๐ก ์ฝ๊ฒ ๋งํ๋ฉด
level
์ด 1์ด๋ฉด ์ฌ์ฅlevel
์ด 2์ด๋ฉด ๋ถ์ฅlevel
์ด 3์ด๋ฉด ๊ณผ์ฅlevel
์ด 4์ด๋ฉด ๋๋ฆฌ
โ ์ด๋ ๊ฒ ํ๋ฉด ๋ช ๋จ๊ณ๋ ์๋์ผ๋ก ํธ๋ฆฌ๋ฅผ ๋ง๋ค ์ ์์ด์!
๐ 6. SELF JOIN์ ์ ์ฌ์ฉํ๋ ค๋ฉด?
SELF JOIN์ ๊ฐ๋ ฅํ์ง๋ง ์ฌ์ฉํ ๋ ์ฃผ์ํ ์ ์ด ์์ด์.
โ ๏ธ 1) ์ฑ๋ฅ ๋ฌธ์ ์ฃผ์!
- SELF JOIN์ ์ฌ๋ฌ ๋ฒ ํ๋ฉด ๋ฐ์ดํฐ๊ฐ ๋ง์ ๋ ์๋๊ฐ ๋๋ ค์ง ์ ์์
- ์ฌ๊ท CTE๋ฅผ ํ์ฉํ๋ฉด ๋ ๊น๋ํ๊ณ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌ ๊ฐ๋ฅ
โ ๏ธ 2) NULL ๊ฐ ์ฒ๋ฆฌ ์ฃผ์!
- ๋ถ๋ชจ๊ฐ ์๋ ๊ฒฝ์ฐ(
NULL
)๋ฅผ ์ ๋๋ก ์ฒ๋ฆฌํด์ผ ํจ - ์์ ์์ ์ฌ์ฅ(manager_id=NULL)์ ๋จผ์ ์ ํํ ์ด์ ๋ ์ด๊ฒ ๋๋ฌธ
โ ๏ธ 3) ์ธ๋ฑ์ค(Index) ์ต์ ํ ํ์
id
,parent_id
๋๋manager_id
๊ฐ์ ์กฐ์ธ์ ์ฐ์ด๋ ์ปฌ๋ผ์ ์ธ๋ฑ์ค๋ฅผ ๊ฑธ์ด์ฃผ๋ฉด ์ฑ๋ฅ ํฅ์๋จ
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์ ๊ผญ ์์์ผ ํด์!