본문 바로가기

Database/MySQL

[데이터베이스(강의)] 8. SQL로 데이터 조회 (join)

 

* SQL에게 JOIN이란?

 - 두 개 이상의 table들에 있는 데이터를 한 번에 조회하는 것

 - 여러 종류의 JOIN이 존재한다.

 


 

[ implicit join  VS  explicit join ]

 

- ID가 1인 임직원이 속한 부서 이름은?

 

 

* implicit join  

 - from절에는 table들만 나열하고 where절에 join condition을 명시하는 방식.

 - old-style join syntax

 - where 절에 selection condition과 join condition이 같이 있기 때문에 가독성이 떨어진다.

 - 복잡한 join 쿼리를 작성하다 보면 실수로 잘못된 쿼리를 작성할 가능성이 크다.

 

 

SELECT D.name

FROM employee E, department D

WHERE  E.id = 1 AND E.dept_id = D.id;


 

* explicit join 

 - from절에 JOIN키워드와 함께 joined table들을 명시하는 방식

 - from절에서 ON 뒤에 join condition이 명시된다.

 - 가독성이 좋다.

 - 복잡한 join쿼리 작성 중에도 실수할 가능성이 적다.

 

 

SELECT D.name

FROM employee E JOIN department D ON E.dept_id = D.id

WHERE  E.id = 1;

 


 

[ inner join  VS  outer join ]

 

 

*  inner join

 - 두 table에서 join condition을 만족하는 tuple들로 resul table을 만드는 join

 - FROM table1 (INNER) JOIN table2 ON join_condition 

 - join condition에 사용 가능한 연산자(operator) : =, <, >, != 등등 여러 비교 연산자가 가능하다.

 - join condition에서 null값을 가지는 tuple은 result table에 포함되지 못한다.

 

 

SELECT *

FROM employee E (INNER) JOIN department D ON E.dept_id = D.id;

 

=> INNER가 생략된 채로 사용하고 있었음.

 

employee table

 

department table

 

쿼리를 실행시켜보면

 

=> employee 테이블에서 dept_id 가 NULL값인 튜플은 포함되지 않음.

 

 


*  outer join

 - 두 table에서 join condition을 만족하지 않는 tuple들도 result table에 포함하는 join

 - FROM table1 LEFT (OUTER) JOIN table2 ON join_condition

 - FROM table1 RIGHT (OUTER) JOIN table2 ON join_condition

 - FROM table1 FULL (OUTER) JOIN table2 ON join_condition

 - join condition에 사용 가능한 연산자 (operator) : =, <, >, != 등등 여러 비교 연산자가 가능하다.

 

 

SELECT *

FROM employee E  LEFT (OUTER)  JOIN department D ON E.dept_id = D.id;

 

=> employee 테이블 + department 테이블 (조건비교 불가한 department 테이블의 튜플 속성들은 NULL)

 

 

 

SELECT *

FROM employee E  RIGHT (OUTER)  JOIN department D ON E.dept_id = D.id;

 

=>  employee 테이블 + department 테이블 (조건비교 불가한 employee 테이블의 튜플 속성들은 NULL)

 


 

(MySQL에서는 FULL OUTER JOIN을 지원하지 않음)

 

SELECT *

FROM employee E  FULL (OUTER)  JOIN department D ON E.dept_id = D.id;

 

=>  employee 테이블 + department 테이블 (조건비교 불가한 두 테이블의 각 튜플 속성들은 NULL)

 


 

* equi join

- join condition에서 = (equality comparator)를 사용하는 join

 

 

SELECT *

FROM employee E (INNER) JOIN department D ON E.dept_id = D.id;

=> inner join 이면서 equi join.

 위에서 사용한 예시 join 모두가 equi join에 해당한다.

 


 

* equi join에 대한 두 가지 시각

 - inner join, outer join 상관없이 = 를 사용한 join이라면 equi join으로 보는 경우.  ** 요 개념으로 설명예정

 - inner join으로 한정해서 = 를 사용한 경우에 equi join으로 보는 경우.

 


 

* using

 - 두 table이 equi join할 때 join하는 attribute의 이름이 같다면, USING으로 간단하게 작성할 수 있다.

 - 이 때 같은 이름의 attribute는 result table에서 한번만 표시된다.

 - FROM table1 (INNER) JOIN table2 USING (attribute(s))

 - FROM table1 LEFT (OUTER) JOIN table2 USING (attribute(s))

 - FROM table1 RIGHT (OUTER) JOIN table2 USING (attribute(s))

 - FROM table1 FULL (OUTER) JOIN table2 USING (attribute(s))

 

 

 

SELECT *

FROM employee E (INNER) JOIN department D ON E.dept_id = D.id;

 

=> department 테이블의 id를 dept_id로 변경하면 (employee 테이블과 동일하게)

 

 

SELECT *

FROM employee E INNER JOIN department D ON E.dept_id = D. dept_id;

 

=> 동일한 이름의 attribute 가 중복된다. 

 

 

 

SELECT *

FROM employee E INNER JOIN department D USING (dept_id);

 

=> 중복되는 attribute가 하나만 맨 앞쪽에 표시된다.

 

 


 

* natural join

 - 두 table에서 같은 이름을 가지는 모든 attribute pair에 대해서 equi join을 수행.

 - join condition을 따로 명시하지 않는다.

 - FROM table1 NATURAL (INNER) JOIN table2

 - FROM table1 NATURAL LEFT (INNER) JOIN table2

 - FROM table1 NATURAL RIGHT (INNER) JOIN table2

 - FROM table1 NATURAL FULL (INNER) JOIN table2

 

 

 

=> department 테이블의 name를 dept_name 으로 변경하면

 

SELECT *

FROM employee E NATURAL INNER JOIN department D;

 

=> 중복되는 attribute가 하나만 맨 앞쪽에 표시된다. (USING을 사용했을 때와 같은 결과)

 


 

=> department 테이블의 dept_name 을 다시 name으로 변경 

(employee 테이블과 department 테이블에서 일치하는 column명이 2개)

department 테이블

 

employee 테이블

 

 

SELECT *

FROM employee E INNER JOIN department D USING(dept_id, name);

 

SELECT *

FROM employee E INNER JOIN department D ON E.dept_id = D.dept_id AND E.name = D.name;

 

 

=> dept_id 와 name 속성 둘다 일치하는 튜플들을 가져오라는 의미 

 employee에서 name은 사람이름, department에서 name은 부서이름이기 때문에 일치하는 속성 없음.

 

 

SELECT *

FROM employee E NATURAL INNER JOIN department D;

 

=> NATURAL을 사용하면 dept_id 와 name을 언급해주지 않아도 알아서 비교한 결과를 보여준다.


 

* cross join 

 - 두 table의 tuple pair로 만들 수 있는 모든 조합(= Cartesian product)을 result table로 반환한다.

 - join condition이 없다.

 - implicit cross join : FROM table1, table2

 - explicit cross join : FROM table1 CROSS JOIN table2

 

 

( explicit cross join )

SELECT

FROM employee CROSS JOIN department;

 

( implicit cross join )

SELECT 

FROM employee, department;

 

 

=> employee 테이블의 속성과 department 테이블 속성 하나하나를 매칭.


 

* cross join @ MySQL

 - MySQL에서는 cross join = inner join = join 이다.

 - CROSS JOIN에 ON(or USING)을 같이 쓰면 inner join으로 동작한다.

 - INNER JOIN(or JOIN)이 ON(or USING) 없이 사용되면 cross join으로 동작한다.

 


 

* self join

 - table이 자기 자신에게 join하는 경우.

 


 

[ join example ]

 

 

- ID가 1003인 부서에 속하는 임직원 중 리더를 제외한 부서원의 ID, 이름, 연봉을 알고 싶다.

 

SELECT E.id, E.name, E.salary

FROM employee E LEFT JOIN department D ON D.dept_id = E.dept_id;

WHERE E.id <> D.leader_id AND E.dept_id = 1003;

 

 

 

- ID가 2001인 프로젝트에 참여한 임직원들의 이름과 직군과 소속 부서 이름을 알고 싶다.

   *employee, department, works_on 세 개의 테이블 조인 필요*

 

요렇게 풀었는데 

더보기

 

SELECT E.id, E.position,D.name

FROM employee E LEFT JOIN works_on W ON E.id = W.empl_id

                               LEFT JOIN department D ON E.dept_id = D.dept_id

WHERE W.proj_id = 2001;

 

** (INNER) JOIN을 사용할지 LEFT JOIN을 사용할지 고민해보기 **

 

 

SELECT E.id, E.position,D.name

FROM works_on W JOIN employee E ON W.empl_id = E.id 

                               *LEFT JOIN department D ON E.dept_id = D.dept_id

WHERE W.proj_id = 2001;

 

 

 

 

 

 

 

* 이 내용은 MySQL 기준 *

 


 

https://www.youtube.com/watch?v=E-khvKjjVv4&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe&index=8