[SQL Fundamentals] 01. ์กฐ์ธ(Join) - ์กฐ์ธ ๊ธฐ๋ฐ ๋ฉ์ปค๋์ฆ
by Hi.Claire๐ฅ๏ธ ๋ฐ์ดํฐ ๋ถ์ SQL Fundamentals (๊ถ์ฒ ๋ฏผ, ์ธํ๋ฐ)
์น์ 1. ์กฐ์ธ(Join) - ์กฐ์ธ ๊ธฐ๋ฐ ๋ฉ์ปค๋์ฆ
1-1. ์กฐ์ธ(Join) ๊ฐ์
์กฐ์ธ(Join)
RDBMS(Relational DBMS, ๊ด๊ณํ DBMS)์์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ด์ ์ค์ํ ๊ธฐ๋ฅ
๋ ๊ฐ ์ด์์ ํ ์ด๋ธ์ ์๋ก ์ฐ๊ฒฐํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถํ ๋ ์ฌ์ฉํ๋ ๊ธฐ๋ฅ์ด๋ค.
๋ ํ ์ด๋ธ์ด join ํค ๊ฐ์ผ๋ก ์ฐ๊ฒฐ๋๋ฉด ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ผ๋ง๋ ์ง ๊ฐ์ ธ์ฌ ์ ์๋ค.
1-2. ์กฐ์ธ ์ ๋ฐ์ดํฐ ์งํฉ ๋ ๋ฒจ์ ๋ณํ ์ดํด
์กฐ์ธ ์ ๋ฐ์ดํฐ ์งํฉ ๋ ๋ฒจ์ ๋ณํ
์กฐ์ธ ์ปฌ๋ผ์ ๊ธฐ์ค์ผ๋ก 1์ธ ์งํฉ(ํด๋น ๋ฐ์ดํฐ๊ฐ uniqueํ๊ฒ ์กด์ฌ)๊ณผ M(ํด๋น ๋ฐ์ดํฐ๊ฐ ์ค๋ณต์ผ๋ก ์กด์ฌ)์ธ ์งํฉ์ด ์์ ๋, ์กฐ์ธ ๊ฒฐ๊ณผ๋ M ์งํฉ์ด ๋๋ค.
์ฆ, 1:M ์กฐ์ธ ์ ๊ฒฐ๊ณผ ์งํฉ์ M ์งํฉ์ ๋ ๋ฒจ์ ๊ทธ๋๋ก ์ ์งํ๋ค.
๋ฌผ๋ก where ์กฐ๊ฑด ๋ฑ์ผ๋ก ๊ฑธ๋ฌ์ง๋ฉด ์กฐ์ธ ๊ฒฐ๊ณผ์ ๋ฐ์ดํฐ ๊ฑด์๋ M ์งํฉ์ ๋ฐ์ดํฐ ๊ฑด์์ ๋์ผํ์ง ์์ ์๋ ์๋ค.
1-3. ์กฐ์ธ ์ค์ต
๊ฐ์ ์ค์ต์ฉ HR ์คํค๋ง์ ERD
Master ํ ์ด๋ธ : ๊ธฐ์ค ์ ๋ณด๋ฅผ ๊ฐ์ง๋ค.
์ด๋ ฅ ํ ์ด๋ธ : ์ด๋ ฅ์ ๊ด๋ฆฌํ๋ค.
์ค์ต ์์
1. ๋ถ์๋ช SALES์ RESEARCH์ ์์ ์ง์๋ค์ ๋ถ์๋ช , ์ง์๋ฒํธ, ์ง์๋ช , JOB ๊ทธ๋ฆฌ๊ณ ๊ณผ๊ฑฐ ๊ธ์ฌ ์ ๋ณด ์ถ์ถ
1
2
3
4
5
6
|
select d.dname, e.empno, e.ename, e.job, esh.fromdate, esh.todate, esh.sal
from dept d
join emp e on d.deptno = e.deptno
join emp_salary_hist esh on e.empno = esh.empno
where d.dname in ('SALES', 'RESEARCH')
order by d.dname, e.empno, esh.fromdate;
|
์กฐ์ธ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ ์งํฉ ๋ ๋ฒจ์ ์ด๋ป๊ฒ ๋ณํํ ๊น?
dept์ emp ํ ์ด๋ธ์ ๊ด๊ณ๊ฐ 1:M์ด๊ณ , ๋ค์ emp์ emp_salary_hist ํ ์ด๋ธ์ ๊ด๊ณ๊ฐ 1:M์ด๋ค.
๋ฐ๋ผ์ ์กฐ์ธ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ ์งํฉ ๋ ๋ฒจ์ emp_salary_hist๋ฅผ ๊ทธ๋๋ก ๋ฐ๋ผ๊ฐ๋ค.
2. ๋ถ์๋ช SALES์ RESEARCH์ ์์ ์ง์๋ค์ ๋ถ์๋ช , ์ง์๋ฒํธ, ์ง์๋ช , JOB ๊ทธ๋ฆฌ๊ณ ๊ณผ๊ฑฐ ๊ธ์ฌ ์ ๋ณด์ค 1983๋ ์ด์ ๋ฐ์ดํฐ๋ ๋ฌด์ํ๊ณ ๋ฐ์ดํฐ ์ถ์ถ
1
2
3
4
5
6
7
|
select d.dname, e.empno, e.ename, e.job, esh.fromdate, esh.todate, esh.sal
from dept d
join emp e on d.deptno = e.deptno
join emp_salary_hist esh on e.empno = esh.empno
where d.dname in ('SALES', 'RESEARCH')
and esh.fromdate >= to_date('19830101', 'yyyymmdd')
order by d.dname, e.empno, esh.fromdate;
|
TO_DATE('๋ฌธ์์ด', '๋ ์ง ํ์')
์ค๋ผํด ๋ฌธ์์ด(varchar) ๋ฐ์ดํฐ๋ฅผ ๋ ์ง(date) ํ์ ์ผ๋ก ๋ณํํ๋ ํจ์
(์) TO_DATE('19830101', 'yyyymmdd')
3. ๋ถ์๋ช SALES์ RESEARCH ์์ ์ง์๋ณ๋ก ๊ณผ๊ฑฐ๋ถํฐ ํ์ฌ๊น์ง ๋ชจ๋ ๊ธ์ฌ๋ฅผ ์ทจํฉํ ํ๊ท ๊ธ์ฌ
1
2
3
4
5
6
7
8
9
10
11
12
|
with temp_01
as
(select d.dname, e.empno, e.ename, esh.fromdate, esh.todate, esh.sal
from dept d
join emp e on d.deptno = e.deptno
join emp_salary_hist esh on e.empno = esh.empno
where d.dname in ('SALES', 'RESEARCH')
order by d.dname, e.empno, esh.fromdate
)
select empno, max(ename) as ename, avg(sal) as avg_sal
from temp_01
group by empno;
|
์ฟผ๋ฆฌ ์ํ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ ์งํฉ ๋ ๋ฒจ์ ์ด๋ป๊ฒ ๋ณํํ ๊น?
๋จผ์ ์กฐ์ธ ๊ฒฐ๊ณผ๋ก๋ ์ค์ต ์์ 1์์ ์ดํด๋ณธ ๋ฐ์ ๊ฐ์ด emp_salary_hist์ ๋ฐ์ดํฐ ์งํฉ ๋ ๋ฒจ์ ๋ฐ๋ฅด๊ฒ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋์ group by๋ฅผ ์ํํ๋ฉด์ ๋ฐ์ดํฐ ์งํฉ ๋ ๋ฒจ์ empno ๋ ๋ฒจ๋ก ๋ฐ๋๊ฒ ๋๋ค.
(์ฃผ์) group by ์ํ ์ select ์ ์๋ group by์ ๋ช ์๋ ์ปฌ๋ผ๊ณผ ์ง๊ณ ํจ์(aggregate function)๋ง ์ฌ ์ ์๋ค.
1-4. ๋ฐ์ดํฐ ์ฐ๊ฒฐ ๊ด๊ณ ํ์ ํ๊ธฐ
๋๋ถ๋ถ์ 1:M ๊ด๊ณ๋ค.
CUSTOMERS์ ORDERS์ ๊ด๊ณ๋ 1:M์ด๋ฉฐ, EMPLOYEES์ ORDERS์ ๊ด๊ณ๋ 1:M์ด๋ค.
๊ทธ๋ฐ๋ฐ PRODUCTS์ ORDERS์ ๊ด๊ณ, ํน์ PRODUCTS์ WAREHOUSE์ ๊ด๊ณ๋ M:N์ด๋ค.
์๋ฅผ ๋ค์ด ์ํ A๋ ์ฃผ๋ฌธ 1์๋ ์์ ์ ์๊ณ , ์ฃผ๋ฌธ 2์๋ ์์ ์ ์๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ์ฃผ๋ฌธ 1์๋ ์ํ A๊ฐ ์์ ์๋ ์๊ณ , ์ํ B๊ฐ ์์ ์๋ ์๋ค.
์ด๋ด ๊ฒฝ์ฐ ๋ณดํต ์ค๊ฐ์ ๊ด๊ณํ ์ด๋ธ์ ๋์ด ๊ด๊ณ๋ฅผ ํ์ด๋ผ ์ ์๋ค.
PRODUCTS์ ORDERS์ ์ฌ์ด์๋ ๊ด๊ณํ ์ด๋ธ ORDER_ITEMS๊ฐ ์๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก PRODUCTS์ WAREHOUSES ์ฌ์ด์๋ ๊ด๊ณํ ์ด๋ธ INVENTORIES๊ฐ ์๋ค.
๊ด๊ณํ ์ด๋ธ๋ก M:N ๊ด๊ณ๋ฅผ ํ์ด๋ด๋ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ๋ค.
์ฃผ๋ฌธ 1์ ์ํ A์ ์ฃผ๋ฌธ์๋ 1๊ฐ, ์ฃผ๋ฌธ 1์ ์ํ B์ ์ฃผ๋ฌธ์๋ 3๊ฐ, ์ฃผ๋ฌธ 2์ ์ํ A์ ์ฃผ๋ฌธ์๋ 10๊ฐ, ์ฃผ๋ฌธ 2์ ์ํ B์ ์ฃผ๋ฌธ์๋ 5๊ฐ ๋ผ๊ณ ๊ฐ์ ํ์.
์ด๋, PRODUCTS์ ORDER_ITEMS์ ๊ด๊ณ๋ 1:M, ORDERS์ ORDER_ITEMS์ ๊ด๊ณ๋ 1:M์ด๋ค.
PRODUCTS์ ORDERS ํ ์ด๋ธ ์ฌ์ด์ ๊ด๊ณํ ์ด๋ธ ORDER_ITEMS๋ฅผ ๋์ด M:N ๊ด๊ณ๋ฅผ ํ์ด๋๋ค.
๊ฐ์ ์ค์ต์ฉ nw ์คํค๋ง
1-5. ์กฐ์ธ ์ค์ต
์ค์ต ์์
1. ๊ณ ๊ฐ๋ช Antonio Moreno๊ฐ 1997๋ ์ ์ฃผ๋ฌธํ ์ฃผ๋ฌธ ์ํ์ ๋ณด๋ฅผ ๊ณ ๊ฐ ์ฃผ์, ์ฃผ๋ฌธ ์์ด๋, ์ฃผ๋ฌธ์ผ์, ๋ฐฐ์ก์ผ์, ๋ฐฐ์ก ์ฃผ์ ๋ฐ ์ฃผ๋ฌธ ์ํ์์ด๋, ์ฃผ๋ฌธ ์ํ๋ช , ์ฃผ๋ฌธ ์ํ๋ณ ๊ธ์ก, ์ฃผ๋ฌธ ์ํ์ด ์ํ ์นดํ ๊ณ ๋ฆฌ๋ช , supplier๋ช ์ ๊ตฌํ ๊ฒ.
1
2
3
4
5
6
7
8
9
10
11
|
select a.contact_name, a.address, b.order_id, b.order_date, b.shipped_date, b.ship_address
, c.product_id, d.product_name, c.amount, e.category_name, f.contact_name as supplier_name
from nw.customers a
join nw.orders b on a.customer_id = b.customer_id
join nw.order_items c on b.order_id = c.order_id
join nw.products d on c.product_id = d.product_id
join nw.categories e on d.category_id = e.category_id
join nw.suppliers f on d.supplier_id = f.supplier_id
where a.contact_name = 'Antonio Moreno'
and b.order_date between to_date('19970101', 'yyyymmdd') and to_date('19971231', 'yyyymmdd')
;
|
์กฐ์ธ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ ์งํฉ ๋ ๋ฒจ์ ์ด๋ป๊ฒ ๋ณํ ๊น?
customer์ orders๊ฐ 1:M, orders์ order_items๊ฐ 1:M ๊ด๊ณ๋ค.
products์ order_items๋ 1:M ๊ด๊ณ๋ค.
categories์ products๋ 1:M, suppliers์ products๋ 1:M ๊ด๊ณ์ด๋ฏ๋ก ๊ฒฐ๊ตญ ๋ฐ์ดํฐ ์งํฉ ๋ ๋ฒจ์ order_items๋ฅผ ๋ฐ๋ผ๊ฐ๊ฒ ๋๋ค.
๋ฐ๋ผ์ ์กฐ์ธ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ๋ order_items์ PK์ธ order_id, product_id๋ฅผ ํค๊ฐ์ผ๋ก ๊ฐ์ง๋ค.
์ต์ข ์ ์ผ๋ก๋ where์ ์ ์ํด ์ ํ๋ ๊ฑด์์ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ๊ฐ ๋์จ๋ค.
๊ฒฐ๊ณผ
'๐พ ๋ฐ์ดํฐ๋ฒ ์ด์ค > ๋ฐ์ดํฐ ๋ถ์ SQL Fundamentals' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ธ๋ก๊ทธ์ ์ ๋ณด
Claire's Study Note
Hi.Claire