๋ฐ์ดํ„ฐ๋ถ„์„๊ฐ€ ๊ณผ์ •/SQL

DAY08. SQL JOIN (Join์˜ ์ข…๋ฅ˜, Cross Join, Inner Join, Outer Join)

LEE_BOMB 2021. 9. 23. 17:17
JOIN์˜ ์ข…๋ฅ˜ (๋ฌผ๋ฆฌ์  ์กฐ์ธ)

Nested Loops Join

Sort Merge Join

Hash Match Join

 

 

 

FOREIGN KEY์กฐ์ธ

ํ…Œ์ด๋ธ”์— ์—†๋Š” ๊ฐ’์„ ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐ(์—ฐ๊ฒฐ)ํ•˜์—ฌ ์ถœ๋ ฅ

<์กฐ์ธ ์ ˆ์ฐจ>
1. ๊ธฐ๋ณธํ‚ค๊ฐ€ ํฌํ•จ๋œ ํ…Œ์ด๋ธ”(master table) ์ƒ์„ฑ
2. ๊ธฐ๋ณธํ‚ค๊ฐ€ ํฌํ•จ๋œ ํ…Œ์ด๋ธ”์— ๋ ˆ์ฝ”๋“œ ์‚ฝ์ž…
3. ์™ธ๋ž˜ํ‚ค๊ฐ€ ํฌํ•จ๋œ ํ…Œ์ด๋ธ”(transaction table) = ๊ฑฐ๋ž˜ํ…Œ์ด๋ธ” ์ƒ์„ฑ
4. ์™ธ๋ž˜ํ‚ค๊ฐ€ ํฌํ•จ๋œ ํ…Œ์ด๋ธ”์— ๋ ˆ์ฝ”๋“œ ์‚ฝ์ž…
* ์กฐ์ธ ํ…Œ์ด๋ธ” ์‚ญ์ œ : ์—ญ์ˆœ. ์™ธ๋ž˜ํ‚ค ํฌํ•จ ํ…Œ์ด๋ธ” ์‚ญ์ œ->๊ธฐ๋ณธํ‚ค ํฌํ•จ ํ…Œ์ด๋ธ” ์‚ญ์ œ
* ๊ฐ•์ œ ํ…Œ์ด๋ธ” ์‚ญ์ œ : DROP TABLE ํ…Œ์ด๋ธ”๋ช… CASCADE CONSTRAINT;

 



1. ๊ธฐ๋ณธํ‚ค๊ฐ€ ํฌํ•จ๋œ ํ…Œ์ด๋ธ” ์ƒ์„ฑ

CREATE TABLE goods(
gcode NUMBER(2) PRIMARY KEY, -- ์ฃผํ‚ค. ์ƒํ’ˆ์ฝ”๋“œ
gname VARCHAR(20), -- ์ƒํ’ˆ๋ช…
price INT -- ๋‹จ๊ฐ€
);


2. ๊ธฐ๋ณธํ‚ค๊ฐ€ ํฌํ•จ๋œ ํ…Œ์ด๋ธ”์— ๋ ˆ์ฝ”๋“œ ์‚ฝ์ž…

INSERT INTO goods VALUES (10, '์‚ฌ๊ณผ', 5000);
INSERT INTO goods VALUES (20, '๋ณต์ˆญ์•„', 8000);
INSERT INTO goods VALUES (30, 'ํฌ๋„', 3000);


3. ์™ธ๋ž˜ํ‚ค๊ฐ€ ํฌํ•จ๋œ ํ…Œ์ด๋ธ” ์ƒ์„ฑ

CREATE TABLE sale(
gcode NUMBER(2) PRIMARY KEY,
sale_date DATE,
su NUMBER(3),
FOREIGN KEY(gcode) REFERENCES goods(gcode)-- ์™ธ๋ž˜ํ‚ค
);


4. ์™ธ๋ž˜ํ‚ค๊ฐ€ ํฌํ•จ๋œ ํ…Œ์ด๋ธ”์— ๋ ˆ์ฝ”๋“œ ์‚ฝ์ž…

INSERT INTO sale VALUES(10, sysdate, 5); 
INSERT INTO sale VALUES(20, sysdate, 10);
INSERT INTO sale VALUES(30, sysdate, 8);

INSERT INTO sale VALUES(40, sysdate, 8); -- error. WHY? ์ฐธ์กฐ ๋ฌด๊ฒฐ์„ฑ ์ œ์•ฝ์กฐ๊ฑด ์œ„๋ฐฐ. ๋งˆ์Šคํ„ฐ ํ…Œ์ด๋ธ”์— ์—†๋Š” gcode ์ถ”๊ฐ€ ๋ถˆ๊ฐ€๋Šฅ


DB๋ฐ˜์˜

COMMIT;

 

๋ฌผ๋ฆฌ์  join์˜ ๋ณ„์นญ ์ง€์ •
SELECT g.gcode, g.gname, s.su, g.price -- (์ถœ์ฒ˜(๋ณ„์นญ).์นผ๋Ÿผ๋ช…)
FROM goods g, sale s -- ํ•œ ์นธ ์‚ฌ์ด๋„๊ธฐ๋กœ ํ…Œ์ด๋ธ” ๋ณ„์นญ ์ง€์ • ๊ฐ€๋Šฅ. SELECT, WHERE์ ˆ์—์„œ๋Š” ASํ•„์š”
WHERE g.gcode = s.gcode -- ์กฐ์ธ์กฐ๊ฑด(ํ•„์ˆ˜). ๋‘ ํ…Œ์ด๋ธ”์„ ์—ฐ๊ฒฐํ•  ๋•Œ, ์–ด๋–ค ์นผ๋Ÿผ์„ ๊ฐ€์ง€๊ณ  ์—ฐ๊ฒฐํ•  ๊ฒƒ์ธ๊ฐ€ 
AND s.su >= 8;-- ์ผ๋ฐ˜์กฐ๊ฑด

 

 

 

 

 

JOIN์˜ ์ข…๋ฅ˜ (๋…ผ๋ฆฌ์  ์กฐ์ธ)

Cross Join ์กฐ๊ฑด ์—†์ด ํ…Œ์ด๋ธ” ์—ฐ๊ฒฐ

Inner Join ์กฐ์ธ ์กฐ๊ฑด์— ๋งŒ์กฑํ•˜๋Š” ํ–‰๋งŒ ๋Œ€์ƒ์œผ๋กœ ์กฐ์ธ

Outer Join ์กฐ์ธ ์กฐ๊ฑด์— ๋งŒ์กฑํ•˜์ง€ ์•Š๋Š” ํ–‰๋„ ํฌํ•จํ•˜๋Š” ์กฐ์ธ

Self Join

 

 

 

Cross Join

= ์นดํ‹ฐ์ „ ์กฐ์ธ

ํŠน๋ณ„ํ•œ ํ‚ค์›Œ๋“œ ์—†์ด SELECT ๋ฌธ์˜ FROM ์ ˆ์— ํ…Œ์ด๋ธ”์„ ์ฝค๋งˆ๋กœ ์—ฐ๊ฒฐ

SELECT * FROM EMP, DEPT;

* Cross Join์˜ ๊ฒฐ๊ณผ๋Š” ์•„๋ฌด๋Ÿฐ ์˜๋ฏธ๋ฅผ ๊ฐ–์ง€ ๋ชปํ•œ๋‹ค.

*์กฐ์ธ ๊ฒฐ๊ณผ๊ฐ€ ์˜๋ฏธ๋ฅผ ๊ฐ–์œผ๋ ค๋ฉด ์กฐ์ธํ•  ๋•Œ ์กฐ๊ฑด์„ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค.

 

 

 

 

 

Inner Join

Inner JOIN์€ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ์กฐ์ธ ๋ฐฉ๋ฒ•

์กฐ์ธ ๋Œ€์ƒ์ด ๋˜๋Š” ๋‘ ํ…Œ์ด๋ธ”์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์กด์žฌํ•˜๋Š” ์ปฌ๋Ÿผ์˜ ๊ฐ’์ด ์ผ์น˜๋˜๋Š” ํ–‰์„ ์—ฐ๊ฒฐํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑ

์กฐ๊ฑด์ด ์ง€์ •๋˜์ง€ ์•Š์œผ๋ฉด cross join๊ณผ ๊ฐ™์€ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰

 

SELECT *
ANSI Inner Join -- ํ‘œ์ค€FROM emp, dept
WHERE emp.deptno=dept.deptno; -- (ํ…Œ์ด๋ธ” ์ถœ์ฒ˜.๊ณตํ†ต์นผ๋Ÿผ)

*๋‘ ์นผ๋Ÿผ์— ์ž๋ฃŒ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์กฐ์ธ -> 14๊ฐœ์˜ ํ–‰, 11๊ฐœ์˜ ์—ด

SELECT *
FROM emp, dept
WHERE emp.deptno=dept.deptno -- ์กฐ์ธ์กฐ๊ฑด
AND ename='SCOTT'; -- ์ผ๋ฐ˜์กฐ๊ฑด


์นผ๋Ÿผ๋ช…์˜ ๋ชจํ˜ธ์„ฑ ํ•ด๊ฒฐ : ์นผ๋Ÿผ๋ช… ํ‘œ๊ธฐ, ๋ณ„์นญ ํ‘œ๊ธฐ

SELECT ename, dname, deptno -- ์œ ์ผ ์นผ๋Ÿผ์€ ์ถœ์ฒ˜ํ‘œ๊ธฐ ์ƒ๋žต ๊ฐ€๋Šฅ
FROM emp, dept
WHERE emp.deptno = dept.deptno -- error. WHY? SELECT์ ˆ๊ณผ WHERE์ ˆ์— ์นผ๋Ÿผ๋ช… ํ‘œ๊ธฐ๊ฐ€ ์—†์Œ
AND ename='SCOTT';

SELECT emp.ename, dept.dname, emp.deptno -- ์นผ๋Ÿผ๋ช… ํ‘œ๊ธฐ
FROM emp, dept
WHERE emp.deptno = dept.deptno
AND ename='SCOTT';

SELECT e.ename, d.dname, e.deptno
FROM emp e, dept d -- ๋ณ„์นญ ์„ค์ •
WHERE e.deptno=d.deptno
AND ename='SCOTT';

SELECT ename, dname, emp.deptno -- deptno๋Š” ์ถœ์ฒ˜ ๋ฐํ˜€์•ผํ•จ 
FROM emp INNER JOIN dept
ON emp.deptno = dept.deptno -- ์กฐ์ธ ์กฐ๊ฑด
WHERE ename = 'SCOTT'; -- ์ผ๋ฐ˜ ์กฐ๊ฑด


[์˜ˆ์ œ] ๋‰ด์š•์—์„œ ๊ทผ๋ฌดํ•˜๋Š” ์‚ฌ์›์˜ ์ด๋ฆ„๊ณผ ๊ธ‰์—ฌ๋ฅผ ์ถœ๋ ฅํ•˜์‹œ์˜ค.(EMP, DEPT ์ด์šฉ)
sub query๋กœ๋„ ํ’€์ด ๊ฐ€๋Šฅ

SELECT ename, sal
FROM emp, dept
WHERE emp.deptno = dept.deptno
AND loc = 'NEW YORK';


[์˜ˆ์ œ] ACCOUNTING ๋ถ€์„œ ์†Œ์† ์‚ฌ์›์˜ ์ด๋ฆ„, ์ž…์‚ฌ์ผ, ๊ทผ๋ฌด์ง€์—ญ์„ ์ถœ๋ ฅํ•˜์‹œ์˜ค.

SELECT ename, hiredate, loc, dname
FROM emp, dept
WHERE emp.deptno = dept.deptno
AND dname = 'ACCOUNTING';


[์˜ˆ์ œ] ์ง๊ธ‰์ด MANAGER์ธ ์‚ฌ์›์˜ ์ด๋ฆ„, ๋ถ€์„œ๋ช…์„ ์ถœ๋ ฅํ•˜์‹œ์˜ค

SELECT ename, dname
FROM emp, dept
WHERE emp.deptno = dept.deptno
AND job = 'MANAGER';


[์˜ˆ์ œ] ํ•™์ƒํ…Œ์ด๋ธ”(student)๊ณผ ๊ต์ˆ˜ํ…Œ์ด๋ธ”(professor) ์กฐ์ธํ•˜๊ธฐ
๊ต์ˆ˜๋ฒˆํ˜ธ(profno) ์นผ๋Ÿผ์„ ๊ธฐ์ค€ ์กฐ์ธํ•˜์—ฌ ํ•™์ƒ๋ช…, ํ•™๊ณผ, ๊ต์ˆ˜๋ช…, ๊ต์ˆ˜๋ฒˆํ˜ธ ์นผ๋Ÿผ์„ ์กฐํšŒํ•˜์‹œ์˜ค.

SELECT *
FROM student, professor
WHERE student.profno = professor.profno; -- 15๊ฐœ ๊ฐ’ ๋„์ถœ : ๊ต์ˆ˜๋ฒˆํ˜ธ๊ฐ€ ์—†๋Š” ํ•™์ƒ์ด ์žˆ์Œ

SELECT s.name ํ•™์ƒ๋ช…, s.deptno1 ํ•™๊ณผ, p.name ๊ต์ˆ˜๋ช…, p.profno ๊ต์ˆ˜๋ฒˆํ˜ธ
FROM student s, professor p
WHERE s.profno = p.profno;


[์˜ˆ์ œ] ์œ— ๋ฌธ์ œ์˜ ๊ฒฐ๊ณผ์—์„œ 101 ํ•™๊ณผ๋งŒ ๊ฒ€์ƒ‰๋˜๋„๋ก ํ•˜์‹œ์˜ค.

SELECT s.name ํ•™์ƒ๋ช…, s.deptno1 ํ•™๊ณผ, p.name ๊ต์ˆ˜๋ช…, p.profno ๊ต์ˆ˜๋ฒˆํ˜ธ
FROM student s, professor p
WHERE s.profno = p.profno
AND s.deptno1 = 101;



 

 

 

Self join
SELECT e1.*, e2.*
FROM emp e1, emp e2; -- ์ถœ๋ ฅ๊ฐ’ ๋ชจ์–‘ : 196ํ–‰ 16์—ด (ํ–‰๋ผ๋ฆฌ ๊ณฑํ•ด์ง€๊ณ , ์—ด์€ ๋”ํ•ด์ง). ์ž๋ฃŒ ๋ถ€์กฑํ•œ ์นผ๋Ÿผ ๊ฐ’์€ NULL

 

 

 

Outer Join : ์ž๋ฃŒ๊ฐ€ ๋ถ€์กฑํ•œ ์นผ๋Ÿผ์— ์ถ”๊ฐ€, ๊ธฐ์ค€ ํ…Œ์ด๋ธ” ์—†์Œ

= Left outer join (์™ผ์ชฝ ํ…Œ์ด๋ธ”์„ ๊ธฐ์ค€์œผ๋กœ ์กฐ์ธ)

SELECT e1.ename ์‚ฌ์›๋ช…, e2.ename ์ƒ์‚ฌ๋ช…
FROM emp e1, emp e2
WHERE e1.mgr = e2.empno (+); -- ์ƒ์‚ฌ๊ฐ€ ์—†๋Š” ๋Œ€ํ‘œ๊นŒ์ง€ ๋ชจ๋‘ ์ถœ๋ ฅ


[์˜ˆ์ œ] EMP ํ…Œ์ด๋ธ”๊ณผ DEPT ํ…Œ์ด๋ธ”์„ ์กฐ์ธํ•˜์—ฌ ์‚ฌ์›์ด๋ฆ„๊ณผ ๋ถ€์„œ๋ฒˆํ˜ธ์™€ ๋ถ€์„œ๋ช…์„ ์ถœ๋ ฅํ•˜์‹œ์˜ค.
DEPT ํ…Œ์ด๋ธ”์˜ 40๋ฒˆ ๋ถ€์„œ์™€ ์กฐ์ธํ•  EMP ํ…Œ์ด๋ธ”์˜ ๋ถ€์„œ๋ฒˆํ˜ธ๊ฐ€ ์—†์ง€๋งŒ, 40๋ฒˆ ๋ถ€์„œ์˜ ์ด๋ฆ„๋„ ์ถœ๋ ฅํ•˜์‹œ์˜ค

SELECT ename, d1.deptno, dname
FROM emp e1, dept d1
WHERE d1.deptno = e1.deptno (+); -- ์ž๋ฃŒ๋ฅผ ๋ชจ๋‘ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํ…Œ์ด๋ธ” : ๊ธฐ์ค€ํ…Œ์ด๋ธ”

 

 

 

ANSI Outer Join (LEFT OUTER JOIN)
SELECT *
FROM DEPT01 LEFT OUTER JOIN DEPT02
ON DEPT01.DEPTNO = DEPT02.DEPTNO;


[์˜ˆ์ œ] ANSI Outer Join์„ ์ด์šฉํ•ด ์ง€๋„๊ต์ˆ˜๊ฐ€ ์—†๋Š” ํ•™์ƒ ์ถœ๋ ฅ

SELECT s.name ํ•™์ƒ๋ช…, p.name ๊ต์ˆ˜๋ช…
FROM student s LEFT OUTER JOIN professor p
USING(profno);


์˜ˆ๋ฌธ์„ SQL๋ฌธ์œผ๋กœ ํ‘œํ˜„ํ•˜๊ธฐ

SELECT s.name ํ•™์ƒ๋ช…, p.name ๊ต์ˆ˜๋ช… 
FROM student s, professor p
WHERE s.profno = p.profno (+);


[์˜ˆ์ œ] Right Outer Join์„ ์ด์šฉํ•˜์—ฌ ์ง€๋„๊ต์ˆ˜๊ฐ€ ์—†๋Š” ํ•™์ƒ ์ถœ๋ ฅ

SELECT s.name ํ•™์ƒ๋ช…, p.name ๊ต์ˆ˜๋ช… 
FROM student s, professor p
WHERE s.profno(+) = p.profno;


[์˜ˆ์ œ] ANSI Right Outer Join์„ ์ด์šฉํ•ด ์ง€๋„๊ต์ˆ˜๊ฐ€ ์—†๋Š” ํ•™์ƒ ์ถœ๋ ฅ (ANSI Right Outer Join)

SELECT s.name ํ•™์ƒ๋ช…, p.name ๊ต์ˆ˜๋ช… 
FROM student s RIGHT OUTER JOIN professor p
USING(profno); -- USING ์ ˆ์—์„œ ์“ฐ์ธ ์กฐ๊ฑด์€ ์ถœ์ฒ˜ํ‘œ๊ธฐ ์—†์ด SELECT์ ˆ์—์„œ ์“ฐ์ผ ์ˆ˜ ์žˆ์Œ

 

 

 

 

์—ฐ์Šต๋ฌธ์ œ

๋ฌธ1) ๊ณ ๊ฐ(user_data)ํ…Œ์ด๋ธ”๊ณผ ์ง€๋ถˆ(pay_data)ํ…Œ์ด๋ธ”์„ inner joinํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถœ๋ ฅํ•˜์‹œ์˜ค.
์กฐ๊ฑด1) ๊ณ ๊ฐID(user_id), ์„ฑ๋ณ„(gender), ์—ฐ๋ น(age), ์ง์—…์œ ํ˜•(job), ์ƒํ’ˆ์œ ํ˜•(product_type), ์ง€๋ถˆ๋ฐฉ๋ฒ•(pay_method), ๊ตฌ๋งค๊ธˆ์•ก(price) ์นผ๋Ÿผ ์ถœ๋ ฅ  
์กฐ๊ฑด2) ๊ณ ๊ฐID ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ

SELECT u.*, p.product_type, p.pay_method, p.price
FROM USER_DATA u, PAY_DATA p 
WHERE u.user_id = p.user_id
ORDER BY u.user_id;
-- [ํ•ด์„ค] ์ „์ฒด ๊ณ ๊ฐ 10์ค‘์—์„œ ์ƒํ’ˆ์„ ๊ตฌ๋งคํ•œ ๊ณ ๊ฐ ๋ ˆ์ฝ”๋“œ ์ถœ๋ ฅ


๋ฌธ2) ๋ฌธ1)์˜ ๊ฒฐ๊ณผ์—์„œ ์„ฑ๋ณ„์ด '์—ฌ์ž'์ด๊ฑฐ๋‚˜ ์ง€๋ถˆ๋ฐฉ๋ฒ•์ด '1.ํ˜„๊ธˆ'์ธ ๊ฒฝ์šฐ๋งŒ ์ถœ๋ ฅํ•˜์‹œ์˜ค.
๋‚จ : gender=1, ์—ฌ : gender=2

SELECT u.*, p.product_type, p.pay_method, p.price
FROM USER_DATA u, PAY_DATA p 
WHERE u.user_id = p.user_id AND (u.gender=2 OR p.pay_method = '1.ํ˜„๊ธˆ')
ORDER BY u.user_id;
-- [ํ•ด์„ค] ์ผ๋ฐ˜ ์กฐ๊ฑด ์ถ”๊ฐ€ : ์ƒํ’ˆ ๊ตฌ๋งค ๊ณ ๊ฐ ์ค‘์—์„œ ํŠน์ • ๊ณ ๊ฐ ์กฐํšŒ


๋ฌธ3) ๊ณ ๊ฐ(user_data)ํ…Œ์ด๋ธ”๊ณผ ์ง€๋ถˆ(pay_data)ํ…Œ์ด๋ธ”์„ left outer joinํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถœ๋ ฅํ•˜์‹œ์˜ค.
์กฐ๊ฑด) ๊ณ ๊ฐID, ์„ฑ๋ณ„, ๋‚˜์ด, ์ƒํ’ˆ์œ ํ˜•, ์ง€๋ถˆ๋ฐฉ๋ฒ• ์นผ๋Ÿผ ์ถœ๋ ฅ   

SELECT u.user_id, gender, age, p.product_type, p.pay_method
FROM USER_DATA u, PAY_DATA p 
WHERE u.user_id = p.user_id(+);
-- [ํ•ด์„ค] ์ „์ฒด ๊ณ ๊ฐ 10์ค‘์—์„œ ์ƒํ’ˆ์„ ๊ตฌ๋งคํ•˜์ง€ ์•Š์€ ๊ณ ๊ฐ๊นŒ์ง€ ์ถœ๋ ฅ


๋ฌธ4) ๊ณ ๊ฐ(user_data)ํ…Œ์ด๋ธ”๊ณผ ๋ฐ˜ํ’ˆ(return_data)ํ…Œ์ด๋ธ”์„ ์ด์šฉํ•˜์—ฌ left outer joinํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถœ๋ ฅํ•˜์‹œ์˜ค.
์กฐ๊ฑด1) ๊ณ ๊ฐID, ์„ฑ๋ณ„, ๋‚˜์ด, ๊ฑฐ์ฃผ์ง€์—ญ, ๋ฐ˜ํ’ˆ์ฝ”๋“œ ์นผ๋Ÿผ ์ถœ๋ ฅ   
์กฐ๊ฑด2) ๋ฐ˜ํ’ˆํ•œ ๊ณ ๊ฐ๋งŒ ์ถœ๋ ฅ

SELECT u.user_id, gender, age, resident, return_code
FROM USER_DATA u, RETURN_DATA r
WHERE u.user_id = r.user_id(+) 
AND return_code IS NOT NULL;
-- [ํ•ด์„ค] ์ „์ฒด ๊ณ ๊ฐ ์ค‘์—์„œ ์ƒํ’ˆ์„ ๋ฐ˜ํ’ˆํ•œ ๊ณ ๊ฐ๋งŒ ์ถœ๋ ฅ 

-- inner join ํ‘œํ˜„ 
SELECT u.user_id, gender, age, resident, return_code
FROM USER_DATA u, RETURN_DATA r
WHERE u.user_id = r.user_id;