๐น 7. Database
14. ๋ฐ์ดํฐ๋ฒ ์ด์ค
[ SQL ๋ฌธ๋ฒ๊ณผ ๊ทธ ๋ณ์ข ๋ค ]
- ๋ช ์์ (explicit) JOIN
1
2
3
SELECT CourseName, TeacherName
FROM Course INNER JOIN Teachers
ON Courses.TeacherID = Teachers.TeacherID
- ๋ฌต์์ (implicit) JOIN
1
2
3
SELECT CourseName, TeacherName
FROM Courses, Teachers
WHERE Courses.TeacherID = Teachers.TeacherID
[ ๋น์ ๊ทํ vs ์ ๊ทํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ]
์ ๊ทํ ๋ฐ์ดํฐ๋ฒ ์ด์ค
: ์ค๋ณต์ ์ต์ํํ๋๋ก ์ค๊ณ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค
- Courses์๋ TeacherID์ฒ๋ผ Teachers์ ๋ํ ์ธ๋ํค๋ฅผ ๊ฐ๋ ์ปฌ๋ผ์ด ์์ ๊ฒ์ด๋ค.
- ์ฅ์ : ๊ต์ฌ ์ ๋ณด(์ด๋ฆ, ์ฃผ์ ๋ฑ๋ฑ)๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ๋ฒ๋ง ์ ์ฅํด๋ ๋๋ค.
- ๋จ์ : ์๋น์์ ์ผ์์ ์ง์๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด JOIN์ ๋ง์ด ํ๊ฒ ๋๋ค.
๋น์ ๊ทํ ๋ฐ์ดํฐ๋ฒ ์ด์ค
: ์ฝ๋ ์๊ฐ์ ์ต์ ํํ๋๋ก ์ค๊ณ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค
- ๋ฐ์ดํฐ๋ฅผ ์ค๋ณตํด์ ์ ์ฅํ ์ ์๋ค.
- ๋ง์ฝ ๊ฐ์ ์ง์๋ฅผ ์์ฃผ ๋ฐ๋ณตํด์ผ ํ๋ค๋ ์ฌ์ค์ ๋ฏธ๋ฆฌ ์๊ณ ์์ผ๋ฉด, ๊ต์ฌ์ ์ด๋ฆ ์ ๋ณด๋ฅผ Courses ํ ์ด๋ธ์ ์ค๋ณตํด ์ ์ฅํ ์๋ ์๋ค.
- ๋์ ๊ท๋ชจ ํ์ฅ์ฑ์ ์คํํ๊ธฐ ์ํด ์์ฃผ ์ฌ์ฉ๋๋ค.
[ SQL๋ฌธ ]
์ ์์ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
1
2
3
4
Courses: CourseID*, CourseName, TeacherID
Teachers: TeacherID*, TeacherName
Students: StudentID*, StudentName
StudentCourses: CourseID*, StudentID*
์ ํ ์ด๋ธ์ ์ฌ์ฉํด ์ง์๋ฌธ์ ๊ตฌํํด๋ณด์.
์ง์ #1: ํ์ ๋ฑ๋ก
- ๋ชจ๋ ํ์์ ๋ชฉ๋ก์ ๋ฝ๊ณ ๊ฐ ํ์์ด ์ผ๋ง๋ ๋ง์ ๊ฐ์๋ฅผ ์๊ฐํ๊ณ ์๋์ง ํ์ธํ๋ ์ง์๋ฌธ
1
2
3
4
5
/* ์๋ชป๋ ์ฝ๋ */
SELECT Students.StudentName, count(*)
FROM Students INNER JOIN StudentCourses
ON Students.StudentID = StudentCourses.StudentID
GROUP BY Students.StudentID
์ด ์ฝ๋์๋ 3๊ฐ์ง ๋ฌธ์ ๊ฐ ์๋ค.
๊ฐ์๋ฅผ ์์ ์๊ฐํ์ง ์๋ ํ์์ ๋ชฉ๋ก์ ํฌํจ๋์ง ์๋๋ค. ์๋ํ๋ฉด Student Courses๊ฐ ์๊ฐ ์ ์ฒญํ ํ์๋ง์ ํฌํจํ๊ธฐ ๋๋ฌธ์ด๋ค.
โ LEFT JOIN์ ์ฌ์ฉํ๋๋ก ๋ณ๊ฒฝํด์ผ ํ๋ค.
LEFT JOIN์ ํ๋๋ก ๋ณ๊ฒฝํด๋ ๋ฌธ์ ๊ฐ ์๋ค. count(*)๋ StudentID๋ก ๋ง๋ค์ด์ง ๊ทธ๋ฃน ๋ด์ ์กด์ฌํ๋ ์์ดํ ์ ๊ฐ์๋ฅผ ์ผ๋ค. ๋ฐ๋ผ์ ๊ฐ์๋ฅผ ์์ ์๊ฐํ์ง ์๋ ํ์์ ๊ฒฝ์ฐ์๋ 1๋ก ๊ณ์ฐ๋๋ ๋ฌธ์ ๊ฐ ์๋ค.
โ count(StudentsCourses.CourseID)์ ๊ฐ์ด ๊ทธ๋ฃน ๋ด์ CourseID ์๋ฅผ ์ธ๋๋ก ๋ณ๊ฒฝํด์ผ ํ๋ค.
Students.StudentID๋ฅผ ์ฌ์ฉํด ๊ทธ๋ฃน์ ๋ง๋ค์์ง๋ง, ์ฌ์ ํ ํ ๊ทธ๋ฃน ์์ ์ฌ๋ฌ ๊ฐ์ StudentName์ด ์กด์ฌํ๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ด๋ค StudentName์ ๋ฐํํด์ผ ํ๋์ง ์ ์ ์๋ค. ๋ชจ๋ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๋ค ํด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๊ทธ ์ฌ์ค์ ์ดํดํ์ง ๋ชปํ ๊ฒ์ด๋ค.
โ first(Students.StudentName)๊ณผ ๊ฐ์ ์ง๊ณ ํจ์(aggregate function)๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์๋ค.
์ ๋ฌธ์ ๋ฅผ ๊ณ ์ณ ๋ค์ ๋ง๋ ์ง์๋ฌธ์ด๋ค.
1
2
3
4
5
6
7
8
/* ์ฒซ ๋ฒ์งธ ํด๋ฒ: ๋ค๋ฅธ ์ง์๋ฌธ์ผ๋ก ๊ฐ์ธ๊ธฐ */
SELECT StudentName, Student.StudentID, Cnt
FROM (
SELECT Students.StudentID, count(StudentCourses.CourseID) as [Cnt]
FROM Students LEFT JOIN StudentCourses
ON Students.StudeentID = StudentCourses.StudentID
GROUP BY Students.StudentID
) T INNER JOIN Students on T.StudentID = Students.StudentID
์ ์ฝ๋ 3๋ฒ์งธ ์ค์์ ๊ทธ๋ฅ ํ์ ์ด๋ฆ์ SELECTํ๋ฉด 3~6๋ฒ ์ค์์ ์ฒ๋ผ ๋ค๋ฅธ ์ง์๋ฌธ์ผ๋ก ๊ฐ์ ํ์๊ฐ ์์ง ์๋๋ผ๊ณ ์๊ฐํ ์ ์๋ค.
์๋ ์ฝ๋๋ ๋ค์ ๋ง๋ค์ด๋ณธ ์๋ชป๋ ํด๊ฒฐ์ฑ ์ฝ๋์ด๋ค.
1
2
3
4
5
/* ์๋ชป๋ ์ฝ๋ */
SELECT StudentName, Students.StudentID, count(StudentCourses.CourseID) as [Cnt]
FROM Students LEFT JOIN StudentCourses
ON Students.StudentID = StudentCourses.StudentID
GROUP BY Students.StudentID
์ด ์ฝ๋๋ ์ด์ ์ฝ๋์ ์ ํํ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ผ ์ ์๋ค. SELECT๊ฐ ๊ฐ๋ฅํ ๊ฒ์ ์ง๊ณ ํจ์๋ GROUP BY ์ ์ ํฌํจ๋ ๊ฐ ๋ฟ์ด๋ค.
๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ ์จ์ผํ๋ค.
1
2
3
4
5
/* ๋ ๋ฒ์งธ ํด๋ฒ: StudentName์ GROUP BY ์ ์ ์ถ๊ฐํ๊ธฐ */
SELECT StudentName, Students.StudentID, count(StudentCourses.CourseID) as [Cnt]
FROM Students LEFT JOIN StudentCourses
ON Students.StudentID = StudentCourses.StudentID
GROUP BY Students.StudentID, Students.StudentName
๋ ๋ค๋ฅธ ํด๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
1
2
3
4
5
6
/* ์ธ ๋ฒ์งธ ํด๋ฒ: ์งํฉ ํจ์๋ก ๊ฐ์ธ๊ธฐ */
SELECT max(StudentName) as [StudentName], Students.StudentID,
count(StudentCourses.CourseID) as [Count]
FROM Students LEFT JOIN StudentCourses
ON Students.StudentID = StudentCourses.StudentID
GROUP BY Students.StudentID
์ง์ #2: ์๊ฐ์ ์ ๊ตฌํ๊ธฐ
- ๋ชจ๋ ๊ต์ฌ ๋ชฉ๋ก๊ณผ ๊ฐ ๊ต์ฌ๊ฐ ๊ฐ๋ฅด์น๋ ํ์ ์๋ฅผ ๊ตฌํ๋ ์ง์๋ฌธ
๋ง์ฝ ํ ๊ต์ฌ๊ฐ ๋์ผํ ํ์์ ์ฌ๋ฌ ๊ฐ์์์ ๊ฐ๋ฅด์น๋ ๊ฒฝ์ฐ, ๊ทธ ๊ฐ๊ฐ์ ๋ค๋ฅธ ํ์์ผ๋ก ๊ฐ์ฃผํด์ ๊ฐ๋ฅด์น๋ ํ์ ์์ ํฉ์ฐํ๋ค. ๊ต์ฌ ๋ฆฌ์คํธ๋ ๊ฐ ๊ต์ฌ๊ฐ ๊ฐ๋ฅด์น๋ ํ์ ์๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌํ๋ฉด ๋๋ค.
1
2
3
4
SELECT TeacherID, count(StudentCourses.CourseID) AS [Number]
FROM Courses INNER JOIN StudentCourses
ON Courses.CourseID = StudentCourses.CourseID
GROUP BY Courses.TeacherID
INNER JOIN์ํ๊ฒ ๋๋ฉด ๊ฐ์๋ฅผ ํ์ง ์๋ ๊ต์ฌ๋ ๋ชฉ๋ก์ ํฌํจ๋์ง ์๋๋ค. ๋ค์๊ณผ ๊ฐ์ด LEFT JOIN์ ํ๋ฉด ๋ชจ๋ ๊ต์ฌ ๋ชฉ๋ก์ ์ป์ ์ ์๋ค.
1
2
3
4
5
6
7
8
SELECT TeacherName, isnull(StudentSize.Number, 0)
FROM Teachers LEFT JOIN
(SELECT TeacherID, count(StudentCourses.CourseID) AS [Number]
FROM Courses INNER JOIN StudentCourses
ON Courses.CourseID = StudentCourses.CourseID
GROUP BY Courses.TeacherID) StudentSize
ON Teachers.TeacherID = StudentSize.TeacherID
ORDER BY StudentSize.Number DESC
NULL๊ฐ์ 0์ผ๋ก ๋ณํํ๊ธฐ ์ํด SELECT ๋ฌธ์์ isnull์ ์ฌ์ฉํ๋ค.
- isnull(a, b): NULL์ด ์๋ ๋ ๊ฐ a, NULL์ผ ๋ ๊ฐ b
[ ์๊ท๋ชจ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ ]
๋ฉด์ ์ฅ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ค๊ณํด๋ณด๋ผ๋ ์์ฒญ์ ๋ฐ์์ ๋! ์ ๊ทผ๋ฒ!
๊ฐ์ฒด ์งํฅ ์ค๊ณ์ ๋น์ทํ ์ ์ด ๋ง๋ค.
1๋จ๊ณ: ๋ชจํธ์ฑ ์ฒ๋ฆฌ
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ด๋ จ๋ ๋ฌธ์ ์๋ ๋ชจํธํ ๋ถ๋ถ์ด ๋ดํฌ๋์ด ์๋ค. ์ ํํ ๋ฌด์์ ์ค๊ณํด์ผ ํ๋์ง ์ดํดํด์ผ ํ๋ค.
[ ์ํํธ ์๋ ๋ํ์ ์ฒด๊ฐ ์ฌ์ฉํ ์์คํ ์ ์ค๊ณ ]
- ์ด ์ ์ฒด์ ๋๋ฆฌ์ ์ด ์ฌ๋ฌ ๊ฐ์ธ์ง ์๋๋ฉด ํ๋๋ง ์๋์ง ์๊ณ ์์ด์ผ ํ๋ค.
- ์ผ๋ง๋ ์ผ๋ฐ์ ์ผ๋ก ์ค๊ณํด์ผ ํ๋์ง ๋ฉด์ ๊ด๊ณผ ๋ ผ์ํด์ผ ํ๋ค.
ex) ์ด๋ค ์ฌ๋์ด ๊ฐ์ ๋น๋ฉ์ ์๋ ์ง์ ๋ ๊ฐ ๋น๋ฆฌ๋ ์ผ์ ๊ต์ฅํ ๋๋ฌผ๋ค. ํ์ง๋ง ๊ทธ๋ ๋ค๊ณ ํด์ ๊ทธ๋ฐ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ด์ผ ํ๋ค๋ ๊ฒ์ ์๋๋ค. ๊ทธ๋ด ์๋ ์๊ณ , ์๋ ์๋ ์๋ค.
โ ๋๋ฌผ๊ฒ ์๊ธฐ๋ ์ผ์ ๋ณ๋์ ๋ฐฉ์์ ์ฌ์ฉํด์, ์ฆ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ณด๊ด๋ ๊ทธ ์ฌ๋์ ๊ฐ์ธ ์ ๋ณด๋ฅผ ๋ณต์ฌํ๋ค๊ฑฐ๋ ํด์ ํด๊ฒฐํ ์๋ ์๋ค.
2๋จ๊ณ: ํต์ฌ ๊ฐ์ฒด ์ ์
๊ทธ ๋ค์์ผ๋ก๋, ์ด ์์คํ ์ ํต์ฌ ๊ฐ์ฒด(core object)๊ฐ ๋ฌด์์ธ์ง ์ดํด๋ด์ผ ํ๋ค. ๋ณดํต ํต์ฌ ๊ฐ์ฒด ํ๋๋น ํ๋์ ํ ์ด๋ธ์ ์ฌ์ฉํ๋ค.
์ํํธ ์๋ ๋ํ์ ์ฒด์ ๊ฒฝ์ฐ Property, Building, Apartment, Tenant, Manager ๋ฑ์ด ํต์ฌ ๊ฐ์ฒด๊ฐ ๋ ์ ์๋ค.
3๋จ๊ณ: ๊ด๊ณ ๋ถ์
ํต์ฌ ๊ฐ์ฒด์ ์ค๊ณฝ์ ์ก๊ณ ๋๋ฉด ์ด๋ป๊ฒ ํ ์ด๋ธ์ ์ค๊ณํด์ผ ํ ์ง ๊ฐ์ ์ก์ ์ ์์ ๊ฒ์ด๋ค. ํ ์ด๋ธ๋ผ๋ฆฌ ์ด๋ค ๊ด๊ณ๊ฐ ์์ ์ง(๋ค๋๋ค, ์ผ๋๋ค ๋ฑ) ์๊ฐํด์ผ ํ๋ค.
Buildings์ Apartments์ ๊ด๊ณ๊ฐ ์ผ-๋-๋ค ๊ด๊ณ๋ผ๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ํํํ ์ ์๋ค.
Apartments | s |
---|---|
ApartmentID | int |
ApartmentAddress | varchar(100) |
BuildingID | int |
Buildings | s |
---|---|
BuildingID | int |
BuildingName | varchar(100) |
BuildidngAddress | varchar(500) |
Apartments ํ ์ด๋ธ๊ณผ Buildings ํ ์ด๋ธ์ BuildingID๋ฅผ ํตํด ์ฐ๊ฒฐ๋๋ค.
ํ ์ฌ๋์ด ํ๋ ์ด์์ ์ํํธ๋ฅผ ์๋ํ ์ ์๋๋ก ํ๊ณ ์ถ๋ค๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ๋ค-๋-๋ค ๊ด๊ณ๋ฅผ ๊ตฌํํ๋ฉด ๋๋ค.
TenantApartments | s |
---|---|
TenantID | int |
ApartmentID | int |
Apartments | s |
---|---|
ApartmentID | int |
ApartmentAddress | varchar(100) |
BuildingID | int |
Tenants | s |
---|---|
TenantID | int |
TenantName | varchar(100) |
TenantAddress | varchar(500) |
TenantApartments ํ ์ด๋ธ์ Tenants์ Apartments ์ฌ์ด์ ๊ด๊ณ๋ฅผ ์ ์ฅํ๊ณ ์๋ค.
4๋จ๊ณ: ํ์ ์กฐ์ฌ
๋ง์ง๋ง์ผ๋ก ์ธ๋ถ์ ์ธ ๋ถ๋ถ์ ์ฑ์ ๋ฃ์ด์ผ ํ๋ค. ํํ ์ํ๋ ์์ ๋ค์ ์ดํด๋ณด๊ณ , ๊ด๋ จ๋ ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ์ ์ฅํ๊ณ ๊ฐ์ ธ์ฌ ๊ฒ์ธ์ง ์ดํดํด์ผ ํ๋ค.
์๋์ ๊ด๊ณ๋ ์ฉ์ด๋ค ํด๊ฑฐ(moving out)๋ ์๋๋น(rent payments)์ ๊ฐ์ ๊ฒ๋ค์ ์ฒ๋ฆฌํด์ผ ํ๋ค. ์ด๋ฐ ์์ ๋ค์ ์ฒ๋ฆฌํ๋ ค๋ฉด ์๋ก์ด ํ ์ด๋ธ์ด ํ์ํ๋ค.
[ ๋๊ท๋ชจ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ ]
๋๊ท๋ชจ์ ๊ท๋ชจ ํ์ฅ์ฑ์ด ๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ค๊ณํ ๋์ JOIN ์ฐ์ฐ(์์ ์์ )์ ์ผ๋ฐ์ ์ผ๋ก ์์ฃผ ๋๋ฆฌ๋ค๊ณ ๊ฐ์ฃผํด์ผ ํ๋ค.
๋ฐ๋ผ์ ๋ฐ์ดํฐ๋ฅผ ๋น์ ๊ทํ(denormalize)ํด์ผ ํ๋ค.