데이터베이스(쉬운코드)

8. SQL로 데이터 조회하기 4부 : join

youbing 2024. 12. 5. 12:59
본 내용은 유튜버 쉬운코드의 강의 "데이터베이스"를 참고하여 작성하였습니다.

 

join의 의미

  • 두 개 이상의 table들에 있는 데이터를 한 번에 조회하는 것
  • 여러 종류의 JOIN이 존재한다.

implicit join

알고 싶은 것 : ID가 1인 임직원이 속한 부서 이름은?

SELECT D.name FROM employee E, department D
  WHERE E.id = 1 AND E.dept_id = D.id;

 

  • E.id = 1에서 우리가 원하는 tuple을 찾고(selection condition), E.dept_id = D.id로 join한다(join condition).

 

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

  • old-style join syntax
  • where절에 selection condition과 join condition이 같이 있기 때문에 가독성이 떨어진다.
  • 복잡한 join 쿼리를 작성하다보면 실수로 잘못된 쿼리를 작성할 가능성이 크다.

 explicit join

위의 implicit join의 단점을 보완하기 위해 join condition을 명시적으로 표기

SELECT D.name
  FROM employee E JOIN department D ON E.dept_id = D.id
  WHERE E.id = 1;

 

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

  • from절에서 ON 뒤에 join condition이 명시된다.
  • 가독성이 좋다.
  • 복잡한 join 쿼리 작성 중에도 실수할 가능성이 적다.

inner join

앞서 사용한 코드가 inner join

 

  • employee 테이블에서 SIMON의 dept_id 값이 NULL
  • department 테이블에서 HR의 id와 대응되는 dept_id가 없음.

-> 결과를 출력했을 때 SIMON과 HR 데이터가 없어짐.

 

inner join : 두 table에서 join condition을 만족하는 tuple들로 result table을 만드는 join

  • FROM table1 [INNER] JOIN table2 ON join_condition
  • join condition에 사용 가능한 연산자 : =, <, >, != 등등 여러 비교 연산자가 가능
  • join condition에서 null 값을 가지는 tuple은 result table에 포함되지 못한다.

outer join

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
  • 방향에 있는 테이블의 null도 포함함.

* join condition에 사용 가능한 연산자는 inner join과 동일

FULL JOIN은 MySQL에서 지원하지 않아 PostgreSQL 사용

 

 


equi join

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

  • 앞서 작성했던 inner join, outer join에 들어가는 코드 모두 join condition에 = 가 들어가므로 equi join

 

equi join에 대한 두 가지 시각

  • inner / outer join 상관없이 = 를 사용한 join이라면 equi join으로 보는 경우 (강의에서는 이거로 사용)
  • inner join으로 한정해서 = 를 사용한 경우에 equi join으로 보는 경우

using

department table에서 id를 dept_id로 변경한 후 결과 -> dept_id가 중복

 

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

결과

  • 두 table이 equi join할 때 join하는 attribute의 이름이 같다면, USING으로 간단하게 작성할 수 있다.
  • 이 때 같은 이름의 attribute는 result table에서 한 번만 표시된다.
  • FROM table1 [INNER] / LEFT [OUTER] / RIGHT [OUTER] / FULL [OUTER] JOIN table2 USING (attribute(s))

natural join

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

  • join condition을 따로 명시하지 않는다.
  • FROM table1 NATURAL [INNER] / LEFT [OUTER] / RIGHT [OUTER] / FULL [OUTER] JOIN table2

 

department 테이블의 name 속성 이름을 dept_name으로 변경

SELECT * FROM employee E NATURAL INNER JOIN department D;

결과

 

만약, department 테이블에서 dept_name으로 변경하지 않으면 위의 코드는 아래 코드처럼 작동된다. -> 아무것도 출력 X

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;

cross join

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

 

SELECT * FROM employee, department;
SELECT * FROM employee CROSS JOIN department; -- 동일한 기능

결과

 

cross join @ MySQL

  • MySQL에서는 cross join = inner join = join이다.
  • ON(or USING)이 있으면 INNER JOIN, 없으면 CROSS JOIN

self join

self join : table이 자기 자신에게 join하는 경우


join을 사용한 두 가지 예제

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

SELECT E.id, E.name, E.salary
  FROM employee E JOIN department D ON E.dept_id = D.id
  WHERE E.id = 1003 AND E.id != D.leader_id;

 

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

SELECT E.name AS empl_name, E.position AS empl_position, D.name AS dept_name
  FROM works_on W JOIN employee E ON W.empl_id = E.id
    LEFT JOIN department D ON E.dept_id = D.id
      WHERE W.proj_id = 2001;
  • LEFT JOIN을 쓰는 이유 : E.dept_id가 null인 경우에도 출력을 해야 하기 때문.
  • E.name, D.name으로만 출력하면 속성 이름이 겹치니까 AS를 사용해서 출력할 이름 변경

참고 사항

1. 오늘 내용은 MySQL 기준입니다. 다른 RDBMS의 SQL 문법은 조금씩 다를 수 있습니다.

 

2. 오늘 영상은 JOIN과 관련하여 대표적으로 중요한 기본기들을 담고 있습니다. 디테일한 내용들은 추가적으로 공부하시는 것이 필요합니다.