2021. 04. 29(목) TIL

36822 단어 TILdbTIL

Database

조인

  • 조인은 두 개 이상의 테이블을 연결지어서 데이터를 조회하는 것이다.
    • 오라클과 같은 관계형데이터베이스는 모든 정보를 하나의 테이블에 저장하는 것이 아니라, 데이터가 정규화되어 여러 테이블에 분산되어 있다.
    • 데이터가 여러 테이블에 흩어져 있기 때문에 사용자가 원하는 데이터를 찾기위해서는 여러 테이블을 다 조회해야 한다.
  • 조인은 여러 테이블에 흩어져 있는 정보중에서 사용자가 원하는 정보만 가져와서 가상의 테이블처럼 만들어서 데이터를 조회하는 것이다.
    • 조인의 예
      • 사원테이블에는 사번, 이름, 소속부서번호가 있다.
      • 부서테이블에는 부서번호, 부서명, 위치가 있다.
      • 아래와 같이 사원테이블에서 사원의 이름을 가져오고, 부서테이블에서 그 사원이 소속된 부서명을 조회해야 한다.
      • 조인은 사원테이블과 부서테이블의 각각의 행을 서로 연관있는 행끼리 연결지어서 새로운 가상의 테이블을 만들고, 그 테이블로부터 필요한 정보를 가져오는 것이다.

조인의 방법

  • 조인문법은 오라클에서만 사용되는 Oracle Join과 모든 RDBMS에서 공통적으로 사용하는 ANSI(표준) Join이 있다.
    • Oracle Join
      SELECT a.col1, b.col2
      FROM table1 a, table2 b
      WHERE a.col2 = b.col2; -- Join 조건
    • ANSI Join
      SELECT a.col1, b.col2
      FROM table1 a [INNER] JOIN table2 b
      ON a.col2 = b.col2
  • 조인이 수행될 때는 두개 이상의 테이블이 사용되는데, 둘 중에 먼저 읽는 테이블을 선행 테이블이라 하고, 뒤에 오는 테이블을 후행 테이블이라고한다.
  • 선행 테이블은 조회할 데이터가 적은 테이블로 선택하는 것이 속도면에서 유리하다

조인의 종류

카티션곱(Cartesian product)

  • 조인에서 가장 중요한 부분은 조인조건을 지정해주는 부분이다.
  • emp테이블과 dept테이블에서 서로 관련있는 데이터를 가져올 때, 조인조건을 보고 가져오게 되는데, 조인조건이 적절하지 않으면 틀린 데이터를 가져오거나 데이터를 가지고 오지 못할 수 있다.
  • 카티션곱은 조인조건을 지정하지 않고, 두 개이상의 테이블을 조인하는 것이다.
  • 조인조건을 지정하지 않으면 조인된 테이블의 모든 데이터를 전부 가져오게된다.
  • ANSI SQL에서는 CROSS JOIN이라고 한다.
  • 이런 경우 조인 작업에 참조되는 테이블의 행수를 모두 곱한 값만큼의 행이 조회결과가 된다.

등가조인(Equi Join)

  • 조인에서 가장 많이 사용되는 조인이다.

  • 등가조인은 선행 테이블에서 데이터를 가져온 후 조인 조건절을 검사해서 동일한 값을 가진 데이터를 후행 테이블에서 꺼내오는 방법이다.

  • 조인조건에서 Equal(=) 연산자를 사용해서 EQUI Join이라고 한다.

  • 등가조인 사용하기

    • emp테이블과 dept 테이블 조인해서 사원이름, 소속부서명 조회하기
      -- Oracle Join
      SELECT e.empno, e.ename, d.dname
      FROM emp e, dept d
      WHERE e.deptno = d.deptno;
      
      -- ANSI Join
      SELECT e.empno, e.ename, d.dname
      FROM emp e JOIN dept d
      ON e.deptno = d.deptn;
    • student테이블과 professor 테이블 조인해서 학생의 이름과 지도교수 이름 조회하기
      -- Oracle Join
      SELECT s.name, p.name
      FROM student s, professor p
      WHERE s.profno = p.profno;
      
      -- ANSI Join
      SELECT s.name, p.name
      FROM student s JOIN professor p
      ON s.profno = p.profno;
    • student테이블과 department테이블, professor테이블을 조인해서 학생명, 전공학과명, 지도교수이름 조회하기
      -- Oracle Join
      SELECT s.name 학생이름, d.dname 학과명, p.name 지도교수명
      FROM student s, department d, professor p
      WHERE s.deptno1 = d.deptno AND s.profno = p.profno;
      
      -- ANSI Join
      SELECT s.name 학생이름, d.dname 학과명, p.name 지도교수명
      FROM student s JOIN department d
      ON s.deptno1 = d.deptno
      JOIN professor p
      ON s.profno = p.profno;
    • deptno1이 101인 학생들의 학생이름, 지도교수를 조회하기
      -- Oracle Join
      SELECT s.name, s.deptno1, p.name
      FROM student s, professor p
      where s.deptno1 = 101 AND s.profno = p.profno
    
      -- ANSI Join
      SELECT s.name, s.deptno1, p.name
      FROM student s JOIN professor p
      ON s.profno = p.profno
      AND s.deptno1 = 101;
    • 조인조건과 검색조건이 동시에 있을 경우, 검색조건을 먼저 검색해서 데이터의 검색범위를 줄여놓고 조인을 수행하게 한다.

-- 테이블 조인하기
-- 사원아이디, 사원명, 소속부서아이디, 소속부서명
-- employees테이블 -> 사원아이디, 사원, 소속부서아이디
-- departments 테이블 - 소속부서명
SELECT employees.employee_id, employees.first_name, employees.DEPARTMENT_ID,
	   departments.department_name
FROM employees, DEPARTMENTS 
WHERE employees.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID;

SELECT A.EMPLOYEE_ID, A.FIRST_NAME, A.DEPARTMENT_ID, B.department_name
FROM  employees A, DEPARTMENTS B
WHERE A.department_id = B.department_id;

-- 테이블조인하기
-- 사원아이디, 이름, 직종아이디, 급여, 직종제목, 직종 최소 급여, 직종 최대 급여 조회하기
-- emlployees 테이블 -> 사원아이디, 이름, 직종아이디, 급여
-- jobs 테이블 -> 직종아이디, 직종제목, 직종 최저급여, 직종 최고급여
SELECT A.EMPLOYEE_ID, A.FIRST_NAME, A.SALARY, B.min_salary, B.max_salary
FROM employees A, jobs B
WHERE A.job_id = b.job_id;

-- 테이블 조인하기
-- 부서아이디, 부서명, 소재지아이디, 소재지 주소, 소재지 도시명 조회하기
-- departments -> 부서아이디, 부서명, 소재지아이디
-- location -> 소재지주소, 소재지 도시명
SELECT A.DEPARTMENT_ID, A.DEPARTMENT_NAME, A.LOCATION_ID, B.street_address, B.city
FROM departments A, LOCATIONS B
WHERE A.LOCATION_ID = B.location_id;

-- 테이블 조인하기
-- 부서관리자가 지정되어 있는 부서의 부서아이디, 부서명, 부서관리자 아이디, 부서관리자 이름 조회하기
-- departments -> 부서아이디, 부서명, 부서관리자아이디,
-- employees -> 부서관리자이름(사원이름)
-- departments의 manager_id는 부서관리자로 지정된 사원의 사원아이디다.
-- departments의 manager_id와 동일한 사원아이디를 가진 사원정보가 조인되어야한다.
SELECT A.DEPARTMENT_ID, A.DEPARTMENT_NAME, A.MANAGER_ID, B.first_name
FROM departments A, employees B
WHERE A.MANAGER_ID = B.employee_id
AND A.manager_id IS NOT NULL;

-- 3개 이상의 테이블 조인하기
-- 사원아이디, 사원이름, 직종아이디, 급여, 직종최저급여, 직종초고급여, 소속부서 아이디, 부서명 조회
-- employees -> 사원아이디, 사원이름, 직종아이디, 급여, 소속부서아이디
-- jobs -> 직종최저급여, 직종최고급여
-- departments -> 부서명
select E.employee_id, E.first_name, E.job_id,
		E.salary, J.min_salary, J.max_salary, 
		E.department_id, D.department_name
from employees E, jobs J, departments D
where E.job_id = J.job_id 
and E.department_id = D.department_id
order by E.employee_id asc; 

-- 100번 사원의 이름, 전화번호, 이메일, 
-- 소속부서아이디, 소속부서명, 소속부서 도시명, 소속부서 소재지주소 조회하기
select E.first_name, E.phone_number, E.email,
       D.department_id, D.department_name,
       L.city, L.street_address
from employees E, departments D, locations L 
where E.employee_id = 100 -- 검색조건
and E.department_id = D.department_id 
and D.location_id = L.location_id;

-- 50번 부서에 소속된 사원들의 사원아이디, 이름, 직종아이디, 직종제목 조회하기
-- 사원아이디, 이름, 직종아이디 --> employees
-- 직종제목 --> jobs
select E.employee_id, E.first_name, J.job_id, J.job_title
from employees E, jobs J 
where E.department_id = 50 
and E.job_id = J.job_id;

-- 급여를 15000이상 받은 사원들의 이름, 직종아이디, 급여, 부서명을 조회하기
-- 급여를 15000이상, 급여, 이름, 직종아이디 --> employees 
-- 부서명 ==> departments
select E.first_name, E.job_id, E.salary, D.department_name
from employees E, departments D 
where E.salary >= 15000
and E.department_id = D.department_id;

-- 100번직원 직원이 관리하는 사원들의 이름, 직종아이디, 직종제목, 부서아이디, 부서명 조회하기
-- 100번직원, 이름, 직종아이디, 부서아아디 --> employees 
-- 직종제목 --> jobs 
-- 부서명 -- >departments
select E.first_name, E.job_id, J.job_title, 
	D.department_id, D.department_name
from employees E, jobs J, departments D 
where E.manager_id = 100
and E.job_id = J.job_id 
and E.department_id = D.department_id;



-- ----------- 퀴즈 ---------------------------
-- 모든 사원들의 사원아이디, 이름, 소속부서아이디, 소속부서명을 조회하기
select E.employee_id, E.first_name, D.department_id, d.department_name
from employees E, departments D
where E.department_id = D.department_id;

-- 모든 사원들의 사원아이디, 이름, 직종아이디, 직종제목을 조회하기
select E.employee_id, E.first_name, j.job_id , J.job_title
from employees E, jobs J
where E.job_id = J.job_id;

-- 사원들 중에서 소속부서가 정해지지 않는 사원의 아이디, 이름, 급여, 직종, 직종최소급여, 직종최대급여를 조회하기
select e.employee_id, e.first_name, e.salary, j.job_id, j.min_salary, j.max_salary
from employees E, jobs J
where E.department_id is not null
and E.job_id = J.job_id;

-- 2007년에 입사한 사원들의 사원아이디, 이름, 소속부서아이디, 소속부서명을 조회하기
select e.employee_id, e.first_name, d.department_id, d.department_name
from employees E, departments D
where e.department_id = d.department_id
and to_char(e.hire_date, 'YYYY') = '2007';

-- 커미션을 받은 사원들의 사원아이디, 이름, 직종, 직종제목, 소속부서아이디, 소속부서명을 조회하기
select e.employee_id, e.first_name, j.job_id, j.job_title, d.department_id, d.department_name
from employees E, jobs J , departments D
where e.commission_pct is not null
and e.department_id = d.department_id
and e.job_id = j.job_id;

-- 직종최소급여가 10000달러 이상인 직종에 종사하고 있는 사원들의 아이디, 이름, 직종아이디, 급여를 조회하기
select e.employee_id, e.first_name, j.job_id, e.salary
from employees E, jobs J
where e.job_id = j.job_id
and j.min_salary >= 10000;

-- 모든 사원들의 사원아이디, 이름, 소속부서아이디, 소속부서명, 해당부서의 소재지 도시 및 주소를 조회하기
select e.employee_id, e.first_name, d.department_id, d.department_name, l.city, l.street_address
from employees E, departments D, locations L
where e.department_id = d.department_id
and d.location_id = l.location_id;

-- 모든 사원들의 사원아이디, 이름, 직종아이디, 직종제목, 소속부서아이디, 소속부서명, 해당부서의 소재지 도시 및 주소
select e.employee_id, e.first_name, j.job_id, j.job_title, d.department_id, d.department_name, l.city, l.street_address
from employees E, departments D, jobs J, locations L
where e.department_id = d.department_id
and e.job_id = j.job_id
and d.location_id = l.location_id;

-- 부서 소재지 국가가 미국에 위치하고 있는 부서의 부서아이디, 부서명, 도시명을 조회하기
select d.department_id, d.department_name, l.city
from departments D, locations L
where l.country_id = 'US';

-- 'Seattle'에서 근무하고 있는 사원들의 사원아이디, 이름, 부서아이디, 부서명을 조회하기
select e.employee_id, e.first_name, d.department_id, d.department_name
from employees E, departments D, locations L
where e.employee_id = d.department_id
and d.location_id = l.location_id
and l.city = 'Seattle';

-- 2006년에 job이 변경된 기록이 있는 사원들의 사원아이디, 이름, 직종아이디를 조회하기
select e.employee_id, e.first_name, e.job_id
from employees E, job_history JH
where e.employee_id = jh.employee_id
and to_char(jh.start_date, 'YYYY') = '2006';

-- 이전에 50번 부서에서 근무한 적이 있는 사원들의 사원아이디, 이름, 근무시작일, 근무종료일, 근무당시 직종아이디를 조회하기
select e.employee_id, e.first_name, jh.start_date, jh.end_date, jh.job_id
from employees E, job_history JH
where e.employee_id = jh.employee_id
and jh.department_id = 50;

-- 사원들 중에서 자신이 근무하고 있는 직종의 최소급여와 최대급여의 평균값보다 적은 급여를 받는 
-- 사원의 아이디, 이름, 직종아이디, 급여, 최소급여, 최대급여, 최소/최대급여 평균값을 조회하기
-- (평균값은 (최소급여+최대급여)/2로 구한다)
select e.employee_id, e.first_name, j.job_id, e.salary, j.min_salary, j.max_salary, ((j.min_salary + j.max_salary) / 2) as average
from employees E, jobs J
where e.job_id = j.job_id
and ((j.min_salary + j.max_salary) / 2) > e.salary;

좋은 웹페이지 즐겨찾기