9월 10일 수업 정리 - JOIN

 RDBMS는 중복을 최소화하는 형태의 데이터 베이스이다.

다른 테이블과 연결해준다. 


****************WHERE + JOIN SELECT SQL 의 모든것 ***********



JOIN : 다른 테이블과 연결하여 데이터를 확장하는 문법

. COLUMN 을 확장한다.


** 행을 확장 -> 집합연산자 ( Union, Intersect minus ) 

-> 다음 번 설명할것 


JOIN 문법 구분 


1. ANSI - SQL 

: RDBMS 에서 사용하는 SQL 표준 문법 

(표준을 잘 지킨 모든RDMBS-MYSQL, MSSQL, POSTGRESQL...에서 실행가능 ) 


2. ORACL   E - SQL 

: ORACLE 사 만의 고유 문법 


ANSI SQL 에 있는 


Natural join : join 하고자 하는 테이블의 컬럼명이 같은 컬럼끼리 연결

      컬럼의 값이 같은 행들끼리 연결 

 

      ANSI - SQL 


SELECT 컬럼 

FROM 테이블명 Natural join 테이블명; 


SELECT emp.empno , deptno, dept.dname 

    FROM emp NATURAL JOIN dept ; 


그냥 

컬럼명이 한쪽 테이블에만 존재할 경우 테이블 한정자를 붙이지 않아도 상관없다. 




SELECT  empno , deptno, dname 

FROM emp Natural JOIN dept; 


-> 테이블간의 column이 같아야되는 제약사항 

조인 컬럼에 테이블 한정자를 붙이면 natural join 에서는 에러로 취급 

NATURAL JOIN 에서는 동일한 컬럼에다가 emp.deptno 나 dept.deptno 같이 한정자를

조인하는 컬럼 앞에다가 붙이면 안된다. 



NATURAL join 을 oracle 문법으로  ( 동일한 행인 deptno 는 앞에 나오네 항상 ) 


1. FROM 절에 조인할 테이블을 나열(    ,     ) 한다.  

2. WHERE 절에 테이블 조인 조건을 기술하다. 


요렇게 써줘야함 


SELECT * 

FROM emp, dept 

WHERE  emp.deptno = dept.deptno; 


컬럼이 여러개의 테이블에 동시에 존재하는 상황에서 테이블 한정자를 붙이지 않아서

오라클 입장에서는 해당 컬럼이 어떤 테이블의 컬럼인지 알수가 없을 때 오류 

: ( 근데 NATURAL JOIN 에서 SELECT 에 공통된 deptno 앞에 한정자를 붙일 수 없음 



SELECT * 

FROM emp, dept 

WHERE deptno = deptno ; 

-----> deptno 가 어디에서 오는 deptno인지 알아야함 



emp 테이블에 있는 부서번호가 dept 테이블에 있는 부서 번호랑 같을때 

인라인뷰 별칭처럼 테이블 별칭을 부여하는 게 가능하다. 


SELECT * 

FROM emp, dept 

WHERE emp.deptno = dept.deptno ; 

--> 


SELECT * 

FROM emp e, dept d 

WHERE e.deptno = d.deptno ; 



ANSI - SQL : JOIN WITH USING 


조인하려는 테이블간 같은 이름의 컬럼이 2개 이상일 때 하나의 컬럼으로만 조인을 하고

싶을 때 사용 



SELECT * 

FROM  emp JOIN dept USING (deptno) ; 


ORACLE 문법에서 


SELECT * 

FROM emp, dept 

WHERE emp.deptno = dept.deptno ; 



ANSI - SQL : JOIN WITH ON - 조인 조건을 개발자가 직접 기술 


NATURAL JOIN , JOIN WITH USING 절을 JOIN WITH ON   절을 통해 표현 가능 


SELECT * 

FROM emp JOIN dept on ( emp.deptno = dept.deptno ) ; 


ORACLE 


SELECT * 

FROM emp, dept 

WHERE emp.deptno = dept.deptno 

AND deptno IN ( 20, 30 ) 

----> 오류 



SELECT * 

FROM emp, dept 

WHERE emp.deptno = dept.deptno 

AND emp.deptno IN ( 20, 30 ) ; 


--> 이것처럼 deptno 가 emp인지 dept 인지 구분을 해줘야 오류가 나지 않음 

논리적인 형태로 구분을 함 


논리적인 형태에 따른 조인 구분 


1. SELF JOIN : 조인하는 테이블이 서로 같은 경우 ( 예를 들어서 emp에는 매니저의 

숫자가 나와있는게 emp 자신의 테이블 


SELECT e.empno , e.ename, e.mgr , m.ename  

FROM emp e JOIN emp m on ( e.mgr = m.empno ) 


여기서 e와 m은 똑같은 emp 라는 테이블에서 그냥 임의로 e . m 으로 나눠서

비교하면서 mgr과 ename을 연결해준것 


ORACLE 


SELECT e.empno, e.ename , e.mgr, m.ename

FROM emp e, emp m 

WHERE e.mgr = m.empno ; 



emp 테이블 : 



emp 테이블에서 mgr 메니저가 empno 에서 찾아볼 수 있다. 



그래서 이 mgr을 empno 로 연결해주려고 한다. self join 


SELECT e.empno, e.ename , e.mgr, m.ename 

FROM emp e JOIN emp m on ( e.mgr = m.empno ) 


---> 오라클에서


SELECT e.empno, e.ename, e.mgr, m.ename  

FROM emp e, emp m 

WHERE e.mgr = m.empno ; 




앞에사진은 14번이 있는데 뒤에 오라클에서 표현한 것은 14번이 없어 


king 의 경우 매니저 컬럼의 값이 null이기 때문에 e.mgr = m.empno 

조건을 충족시키지 못함 

그래서 조인 실패해서 14건중 13건의 데이터만 조회가 된다. 



2. nonqui join 조인 조건이 = 이 아닌 조인 



SELECT * 

FROM emp, dept 

WHERE emp.empno = 7369 

AND   emp.deptno != dept.deptno ; 

emp : 


dept : 


 SELECT * 

 FROM emp, dept 

 WHERE emp.empno = 7369 

   AND emp.deptno != dept.deptno ;





SAL 을 이용해서 등급 구하기 


SELECT * 

FROM salgrade; 




empno, ename sal , 등급 


SELECT empno, ename, sal, grade 

FROM emp, salgrade 

WHERE emp.sal >= losal 

AND     sal <= hisal; 

:


SQL 처럼 하면 


SELECT empno, ename, sal, grade 

FROM emp, salgrade 

WHERE sal BETWEEN losal AND hisal ; 


-> 위에랑 동일 


위에 sql을 ansi - sql로 변경


SELECT empno, ename, sal, grade 

FROM emp JOIN salgrade ON ( sal >= losal and sal <= hisal );  










내 정리 


1. NATURAL JOIN 과 ORACLE 


SELECT * 

FROM emp, dept 

WHERE emp.deptno = dept.deptno 


와 


SELECT * 

FROM emp NATURAL JOIN dept 


동일


만약  

SELECT * 

FROM emp, dept 

이렇게 쓰면 deptno 가 동일한 절이 생성되지 않기때문에 더 길어짐 


2. JOIN WITH USING 과 ORACLE 


JOIN WITH USING 에서 


SELECT * 

FROM emp JOIN dept USING (deptno) ; 


이거는 emp 테이블이랑 dept 테이블을 같이 합칠건데 deptno 가 동일한 애들을 바탕으로

할거다. 


그러면 deptno 는 조인한거니까 맨 앞으로 출력이 되고 deptno 가 emp에서 20이면 dept

에서 emp 가 20 인 사람은 research  10 인 사람은 accounting  30인 사람은 sales 라고 

옆에 붙어서 나오게 된다.


SELECT * 

FROM dept 



  

SELECT *

FROM emp 




------JOIN WITH USING 으로 쓴것 


SELECT * 

FROM emp JOIN dept USING (deptno) ;


-- using 뒤에 deptno 에 괄호로 묶어 주어야 한다. 


얘는 


 


-----------위에 있던 

SELECT * 

FROM emp JOIN dept USING (deptno) ;

-----얘를 ORACLE에서 쓰면 


SELECT * 

FROM emp, dept 

WHERE emp.deptno = dept.deptno ; 


얘는 앞에 deptno 가 나오지 않고 중간에 deptno 가 동일한 곳을 같이 두개행으로 써준다. 

두개를 그냥 붙여준 것 같이 





중요한 것 : 


SELECT  *                               

FROM emp a JOIN emp b 

ON  ( m.mgr = s.empno ) ; 


여기서는 열이 13열만 나오는데 

자식인 emp 배열에서 mgr이 없었던 king 이라는 애는 둘이 join 을 했을때 사라지게

된다. 즉  join을 한 뒤 자식배열이 늘 원래의 데이터테이블처럼 뽑아져 나오는 것은 아니다. 


원래 emp 테이블 


salgrade와 emp 테이블을 조인한 테이블 


emp 테이블과 salgrade 테이블이 합쳐졌는데 

emp 테이블에 있는 ename을 보면 king 이 사라져 있음 



문제풀기 


데이터 결합 ( 실습 join 0 ) 

emp, dept 테이블을 이용하기 



푸는 과정

1. 우선 각 COLUMN 이 어디서 오는지를 보기 

SELECT *

FROM emp 

얘랑 


SELECT * 

FROM dept 

얘를 비교해서 보기 


emp 에서는 empno , ename 를 가져오고 


dept 에서는 dname을 가져오고 

공통은 deptno 이다. 

SQL 로 

SELECT empno, ename, emp.deptno, dname

FROM emp, dept 

WHERE emp.deptno = dept.deptno 

ORDER BY emp.deptno 


natural join 으로 

SELECT empno, ename, deptno, dname 

FROM emp NATURAL JOIN dept 

ORDER BY deptno 


* NATURAL JOIN 을 할때는 공통되는 COLUMN에는 한정자를 붙이면 안된다 

나머지는 COLUMN에 한정자를 붙이지 않은 이유는 각각 한개만 있기 때문에 구분해줄

필요가 없다. 


join with on 으로 


SELECT empno, ename, emp.deptno, dname 

FROM emp JOIN dept ON ( emp.deptno = dept.deptno ) 

ORDER BY deptno 



데이터결합 ( 실습 join 0 _ 1 ) 

emp , dept 테이블을 이용하여 조회하기 


푸는 과정 


1.emp와 dept를 먼저 조회해서 전체를 파악하고 


SELECT * 

FROM emp 


SELECT * 

FROM dept 


2. emp 와 dept 에서 조회결과로 나올 애가 들어 있는 테이블을 확인해준다. 


SELECT *  empno, ename 

FROM emp 


SELECT *  dname 

FROM dept 


공통으로 들어가는 것 deptno 


여기에 추가된 조건이 : deptno 가 10이거나 30 인아이 


ORACLE 로 풀기 


SELECT empno, ename , emp.deptno , dname 

FROM emp, dept 

WHERE emp.deptno = dept.deptno 

AND emp.deptno in ( 10, 30 ) 


-NATURAL JOIN 

SELECT empno, ename, deptno, dname 

FROM emp NATURAL JOIN dept 

WHERE deptno IN ( 10, 30 );


SELECT empno, ename, deptno, dname 

FROM emp NATURAL JOIN dept 

WHERE deptno = 10 

OR    deptno = 30 



-JOIN WITH USING 으로 


SELECT empno, ename, deptno, dname 

FROM emp JOIN dept USING (deptno) 

WHERE deptno IN ( 10, 30 );



- JOIN WITH ON 으로 


SELECT empno, ename, emp.deptno, dname 

FROM emp JOIN dept ON (emp.deptno = dept.deptno) 

WHERE emp.deptno IN ( 10, 30 )





*진짜 중요한것 : join with USING 에서도 deptno같은 동일한 column에 한정자를

붙여주지 않아야 한다. 

JOIN WITH ON 은 붙여줘야 한다. 


데이터결합 ( 실습 join 0_3 ) 



1.ORACLE로 풀기

SELECT a.empno , a.ename , a.sal , a.deptno,  b.dname 

FROM emp a, dept b 

WHERE a.deptno = b.deptno 

AND    sal > 2500 

AND   empno > 7600 


2.NATURAL JOIN 으로 풀기 

SELECT empno , ename , sal , deptno, dname 

FROM emp NATURAL JOIN dept 

WHERE sal > 2500 

AND empno > 7600 


natural join 에서는 동일한 컬럼인 deptno 에 한정자를 붙이면 안되고 

또 동일한 컬럼이 deptno 뿐이니까 완전 한정자를 전체를 다 안붙여도 가능하고

한정자를 deptno 빼고 나머지에 붙여도 가능하다


SELECT a.empno , a.ename , a.sal , deptno, b.dname 

FROM emp a NATURAL JOIN dept b 

WHERE a.sal > 2500 

AND a.empno > 7600 


3. JOIN WITH USING 으로 풀기 


SELECT a.empno , a.ename , a.sal , deptno, b.dname 

FROM emp a JOIN dept b USING (deptno)  

WHERE a.sal > 2500 

AND a.empno > 7600 ;


* using 뒤에 ( ) 괄호 꼭 붙여야지 안붙이면 작동이 안되네


4. JOIN WITH ON 으로 풀기 


-SELECT a.empno , a.ename , a.sal , a.deptno, b.dname 

FROM emp a JOIN dept b ON ( a.deptno = b.deptno

AND a.sal > 2500 

AND a.empno > 7600);


-SELECT a.empno , a.ename , a.sal , a.deptno, b.dname 

FROM emp a JOIN dept b ON  a.deptno = b.deptno

AND a.sal > 2500 

AND a.empno > 7600;



데이터 결합 실습 JOIN0_4 

EMP , DEPT 테이블 이용 


oracle 이용 하기 


SELECT e.empno, e.ename, e.sal, d.deptno, d.dname

FROM emp e , dept d 

WHERE e.deptno = d.deptno 

AND    e.sal > 2500 

AND    e.empno >7600

AND    d.dname = 'RESEARCH' 

ORDER BY ename;

NATURAL JOIN 이용하기 


SELECT e.empno, e.ename, e.sal, deptno, d.dname

FROM emp e NATURAL JOIN dept d 

WHERE  e.sal > 2500 

AND    e.empno >7600

AND    d.dname = 'RESEARCH'  

ORDER BY ename;


또는 NATURAL JOIN 은 공통된 COLUMN이 하나만 있는 애일때이고

deptno 에는 한정자를 붙이지 않아야 한다

공통된 column이 하나니까 다 한정자를 붙이지 않아도 무방 


SELECT empno, ename, sal, deptno, dname

FROM emp NATURAL JOIN dept  

WHERE  sal > 2500 

AND    empno >7600

AND    dname = 'RESEARCH' 

ORDER BY ename;



JOIN WITH USING 이용하기 



SELECT empno, ename, sal, deptno, dname

FROM emp JOIN dept USING (deptno)   

WHERE  sal > 2500 

AND    empno >7600

AND    dname = 'RESEARCH' 

ORDER BY ename ;




JOIN WITH ON 이용하기 



진짜 중요한거는 : NATURAL JOIN 할때는 여기에 벌써 DEPTNO 라는 공통의 COLUMN 이 있기 때문에 em.deptno 와 dept.deptno 가 동일하다는 것은 안나타내

주어도 된다. 


하지만 JOIN WITH ON이나 JOIN WITH USING 에서는 저부분을 명시해주어야 하고

그것을 표현하는 것은 JOIN WITH USING 에서는 뒤에 ( deptno ) 

JOIN WITH ON 에서는 ON뒤에 ( em.deptno = dept.deptno ) 을 명시해주어야 한다. 


 SELECT e.empno, e.ename, e.sal, d.deptno, d.dname

FROM emp e JOIN dept d ON e.deptno = d.deptno 

AND e.sal > 2500 

AND    e.empno >7600

AND    d.dname = 'RESEARCH'  

ORDER BY ename;













댓글