Oracle

[Oracle] Join

eunnys 2024. 2. 13. 11:51

-- 202422()

 

*** 조인(Join)

- 둘 이상의 테이블들을 결합하여 데이터를 조인하는 것

- 일반적으로 PKFK의 관계를 갖고 있는 테이블을 통해 검색을 한다.

- 관계형 데이터베이스의 가장 큰 장점이면서 가장 중요한 핵심 기능이다.

- 조인을 하는 이유는 데이터의 무결성을 유지하기 위하여 테이블을 정규화하는

작업으로 인해 둘 이상으로 나뉘어진 정보를 조회하기 위한 목적을 가지고 있다.

 

 

** Cross Join(=카르테시안 조인) : A x B

-- 직원이름, 월급, 부서명

select e.first_name, e.salary, d.department_name

from departments d, employees e;

 

 

** EQUI Join : PKFK가같아야 조인 처리된다

-- 직원이름, 월급, 부서명

select e.first_name, e.salary, d.department_name

from departments d, employees e

where d.department_id = e.department_id;

 

-- 부서명(departments)과 도시명(locations)을 조회

select * from departments;

select * from locations;

 

select d.department_name, l.city

from departments d, locations l

where l.location_id = d.location_id;

 

 

-- 부서명, 나라명, 도시명

select * from countries;

 

select d.department_name, c.country_name, l.city

from departments d, countries c, locations l

where

d.location_id = l.location_id and

c.country_id = l.country_id;

 

 

 

*** Inner Join 

-- 결과는 EQUI Join과 동일

-- 문법은 다르다

-- inner 키워드는 생략 가능

-- where --> on

 

 

-- 부서명(departments)과 도시명(locations)을 조회

select d.department_name, l.city

from departments d inner join locations l

ON l.location_id = d.location_id;

 

 

-- INNER 키워드 생략

select d.department_name, l.city

from departments d join locations l

ON l.location_id = d.location_id;

 

 

-- ON 대신 USING 사용

select d.department_name, l.city

from departments d join locations l

using (location_id);

 

 

-- 직원의 이름, 급여, 부서명을 join ~ on, join ~ using 사용하여 출력

-- 1) 오라클 문법

select e.first_name, e.salary, d.department_name

from employees e, departments d

where e.department_id = d.department_id;

 

 

-- 2) ANSI 표준 (join ~ on) : inner 생략 가능

select e.first_name, e.salary, d.department_name

from employees e join departments d

on e.department_id = d.department_id;

 

 

-- 3) ANSI 표준 (join ~ using)

select e.first_name, e.salary, d.department_name

from employees e join departments d

using (department_id);

 

 

 

** 3개의 테이블에서 조인하기

-- [연습] 부서명, 도시명, 나라명을 조회

 

-- 1) 오라클 문법

select d.department_name, l.city , c.country_name

from departments d, locations l, countries c

where

d.location_id = l.location_id and

l.country_id = c.country_id;

 

 

-- 2) ANSI 표준 (join ~ on) : join한 결과에 다시 join

select d.department_name, l.city , c.country_name

from departments d join locations l

on d.location_id = l.location_id

join countries c

on l.country_id = c.country_id;

 

 

-- 3) ANSI 표준 (join ~ using)

select d.department_name, l.city , c.country_name

from departments d join locations l

using (location_id)

join countries c

using (country_id);

 

 

-- [연습] 이름, 입사일, 근속년수, 부서명, 직급이름, 급여 조회

-- 1) 오라클 문법

select

e.first_name, e.hire_date,

floor(months_between(sysdate, hire_date) / 12) as 근속년수,

d.department_name, j.job_title, e.salary

from employees e, departments d, jobs j

where

e.department_id = d.department_id and

e.job_id = j.job_id

order by 4;

 

 

-- 2) join ~ on

select

e.first_name, e.hire_date,

floor(months_between(sysdate, hire_date) / 12) as 근속년수,

d.department_name, j.job_title, e.salary

from employees e join departments d

on e.department_id = d.department_id

join jobs j

on e.job_id = j.job_id

order by 4;

 

 

-- 3) join ~ using

select

e.first_name, e.hire_date,

floor(months_between(sysdate, hire_date) / 12) as 근속년수,

d.department_name, j.job_title, e.salary

from employees e join departments d

using (department_id)

join jobs j

using (job_id)

order by 4;

 

 

-- 4) 뷰로 만들기

create view MY_VIEW as (

select

e.first_name, e.hire_date,

floor(months_between(sysdate, hire_date) / 12) as 근속년수,

d.department_name, j.job_title, e.salary

from employees e, departments d, jobs j

where

e.department_id = d.department_id and

e.job_id = j.job_id

);

 

 

select * from my_view;

drop view my_view;

 

 

 

*** Outer Join 

-- FK를 가진 테이블의 데이터가 null일 때 조회되지 않는 레코드가 생기므로,

-- 조회되지 않는 데이터까지 조회하기 위한 조인 방법

-- join 조건이 같지 않을 경우에도 결과를 반환받고자 할 때

-- 종류: left outer, right outer, full outer

 

 

** Left Outer

-- 먼저 왼쪽 테이블의 데이터를 가져오고, 오른쪽 테이블을 가져온다

-- 이 때 join 조건이 맞지 않으면 null로 채운다

-- PK 부모 테이블을 앞에, FK 자식 테이블을 뒤에 둠

-- 부모 테이블에 (+)를 붙인다

 

 

-- 이름과 부서명을 조회

-- 1) 오라클 문법

-- 부모의 PK 쪽에 (+)를 붙임

select e.first_name, d.department_name

from departments d, employees e

where d.department_id(+) = e.department_id;

 

 

-- 2) LEFT OUTER JOIN ~ ON

select e.first_name, d.department_name

from employees e left outer join departments d

on d.department_id = e.department_id;

 

 

-- 3) LEFT OUTER JOIN ~ USING

select e.first_name, d.department_name

from employees e left outer join departments d

using (department_id);

 

 

-- 3) RIGHT OUTER JOIN ~ USING ==> 자식 테이블이 오른쪽에 있을 때

select e.first_name, d.department_name

from departments d right outer join employees e

using (department_id);

 

 

 

*** Self Join 

-- PK, FK가 하나의 테이블 내의 존재

 

-- 직원 아이디, 이름, 매니저 아이디, 이름을 조회

-- 니나의 매니저는 스티븐

-- 1) 오라클 문법

select e2.employee_id, e2.first_name, e2.manager_id, e1.first_name

from employees e1, employees e2

where e2.manager_id = e1.employee_id;

 

 

-- 2) JOIN ~ ON

select e2.employee_id, e2.first_name, e2.manager_id, e1.first_name

from employees e1 join employees e2

on e2.manager_id = e1.employee_id;

 

 

-- 3) JOIN ~ USING은 컬럼명이 달라서 사용할 수 없음

 

 

-- 107명 모든 직원의 정보가 출력되도록 outer join

select e2.employee_id, e2.first_name, e2.manager_id, e1.first_name

from employees e1 right outer join employees e2

on e2.manager_id = e1.employee_id

order by 1;

 

 

-- [연습문제]

-- 1. join을 이용하여 사원번호가 100인 사원의 사원번호, 부서번호, 부서이름 조회

select employee_id, department_id, department_name

from employees join departments

using (department_id)

where employee_id = 100;

 

 

-- 2. inner join을 이용하여 직원의 이름과 그 직원이 속한 부서의 도사명, 지역명을 조회

select e.first_name, l.city, r.region_name

from employees e, departments d, locations l , countries c, regions r

where e.department_id = d.department_id and

d.location_id = l.location_id and

l.country_id = c.country_id and

c.region_id = r.region_id;

 

 

-- 3. 100번 부서에 속하는 직원의 이름과 직원의 job_title, 부서가 있는 도시명을 조회

select e.first_name, j.job_title, l.city

from employees e, departments d, jobs j, locations l

where

e.department_id = 100 and

j.job_id = e.job_id and

e.department_id = d.department_id and

d.location_id = l.location_id;

 

 

 

[연습문제]

 

-- 1. JOIN을 이용하여 사원ID100번인 사원의 부서번호와 부서이름을 출력하시오

select e.department_id, d.department_name

from employees e, departments d

where

e.employee_id = 100

and

d.department_id = e.department_id;

 

 

-- 2. INNER JOIN을 이용하여 사원이름과 함께 그 사원이 소속된 도시이름과 지역명을 출력하시오

select e.first_name, l.city, r.region_name

from employees e, locations l, regions r, departments d, countries c

where

d.department_id = e.department_id

and

d.location_id = l.location_id

and

l.country_id = c.country_id

and

c.region_id = r.region_id;

 

 

-- 3. INNER JOINUSING 연산자를 사용하여 100번 부서에 속하는

-- 직원명과 직원의 담당 업무명, 속한 부서의 도시명을 출력하시오.

-- (100번 부서에는 직원 6명있음)

select e.first_name, j.job_title, l.city

from employees e, departments d, jobs j, locations l

where

e.department_id = 100

and

j.job_id = e.job_id

and

e.department_id = d.department_id

and

d.location_id = l.location_id;

 

 

-- 4. JOIN을 사용하여 커미션을 받는 모든 사원의 이름, 부서ID, 도시명을 출력하시오

select e.first_name, d.department_id, l.city

from employees e, departments d, locations l

where

e.commission_pct is not null

and

e.department_id = d.department_id(+)

and

d.location_id = l.location_id(+)

order by 1;

 

 

-- 5. INNER JOIN과 와일드카드를 사용하여 이름에 A가 포함된 모든 사원의 이름과 부서명을 출력하시오(, 대소문자 구분 없음)

select e.first_name, d.department_name

from employees e, departments d

where

d.department_id = e.department_id

and

e.first_name like '%A%';

 

 

-- 6. JOIN을 사용하여 Seattle에 근무하는 모든 사원의 이름, 업무, 부서번호 및 부서명을 출력하시오

select first_name, job_title, department_id, department_name

from employees join departments

using (department_id)

join jobs

using (job_id)

join locations

using (location_id)

where

city = 'Seattle';

 

 

-- 7. SELF 조인을 사용하여 사원의 이름 및 사원번호와 매니저 이름 및 매니저 번호와 함께 조회하시오.

select e2.first_name, e2.employee_id, e1.first_name, e2.manager_id

from employees e1, employees e2

where e2.manager_id = e1.employee_id;

 

 

-- 8. OUTER JOIN, SELF JOIN을 사용하여 관리자가 없는 사원을 포함하여 사원번호를 기준으로 내림차순 정렬하여 조회

select e2.first_name as "직원명", e2.employee_id, e1.first_name as "매니저명", e2.manager_id

from employees e1 right outer join employees e2

on e2.manager_id = e1.employee_id

order by 1 desc;

 

select e2.first_name as "직원명", e2.employee_id, e1.first_name as "매니저명", e2.manager_id

from employees e2 left outer join employees e1

on e2.manager_id = e1.employee_id

order by 1 desc;

 

 

-- 9. SELF JOIN을 사용하여 'Oliver' 사원의 부서명, 그 사원과 동일한 부서에서 근무하는 동료 사원의 이름을 조회.

-- , 각 열의 별칭은 부서명, 동료로 할 것.

select d.department_name as 부서명, temp.first_name as 동료 from

(select first_name, department_id from employees

where department_id = (select department_id

from employees

where first_name = 'Oliver')

) temp, departments d

where temp.department_id = d.department_id

order by 1;

 

 

-- 10. SELF JOIN을 사용하여 관리자보다 먼저 입사한 모든 사원의 이름 및 입사일을 매니저 이름 및 입사일과 함께 출력하시오

select e1.first_name, e1.hire_date, e2.first_name as "매니저이름", e2.hire_date as "입사일"

from employees e1 join employees e2

on e1.manager_id = e2.employee_id

and e1.hire_date < e2.hire_date;

 

 

-- 11. Last name‘King’Manager로 둔 사원의 이름과 급여를 조회하시오.

select e1.first_name, e1.salary

from employees e1, employees e2

where

e1.manager_id = e2.employee_id

and

e2.last_name = 'King';

 

 

-- 12. Finance부서의 사원에 대한 부서번호, 사원이름 및 담당 업무를 표시하시오

select department_id, first_name, job_title

from departments join employees

using (department_id)

join jobs

using (job_id)

where department_name = 'Finance';

 

 

-- 13. 평균 급여보다 많은 급여를 받고 이름에 M이 포함된 사원과 같은 부서에서

-- 근무하는 사원의 사원번호, 이름, 급여를 조회하시오

select employee_id, first_name, salary

from employees

where

salary >= (select avg(salary)

from employees)

and

first_name like '%M%';

'Oracle' 카테고리의 다른 글

[Oracle] 시퀀스  (0) 2024.02.13
[Oracle] DDL  (0) 2024.02.13
[Oracle] 서브쿼리  (0) 2024.02.13
[Oracle] 오라클 함수  (0) 2024.02.13
[Oracle] 오라클 집합  (0) 2024.02.13