Or07Join
/********
# 파일명 : Or07Join.sql
# 테이블 조인
# 설명 : 두 개 이상의 테이블을 동시에 참조하여 데이터를 가져와야할 때 사용하는 쿼리문
********/
/*
[1] inner join(내부조인)
- 두 개 이상의 테이블로부터 자료를 검색하기 위해서 join을 사용
일반적으로 primary key(기본키)와 foreign key(외래키,참조키)를 사용하여 join하는 경우가 대부분
- 가장 많이 사용되는 조인문으로 테이블간에 연결조건을 모두 만족하는 행을 검색하는데 사용
- 검색시 검색되는 컬럼이 조인하는 테이블 모드에 존재한다면
반드시 컬럼명에 테이블 이름을 다음의 형태로 기술해야한다. "테이블명.컬럼명"
- inner join은 자식테이블(foreign key가 있는 테이블)을 기준으로 모든 데이터를 가져온다.
예를들면 자식테이블의 전체 레코드가 10개면 inner join한 결과의 레코드 수는 10개이다.
사용구문
[2개의 테이블을 조인할때]
방법1(표준 SQL방식)
select
컬럼1, 컬럼2, ... , 컬럼N
from
테이블1 inner join 테이블2
on
테이블1.기본키컬럼 = 테이블2.기본키컬럼
where 조건1, 조건2
방법2(Oracle 방식)
select
컬럼1, 컬럼2, .... , 컬럼N
from
테이블1, 테이블2
where
테이블1.기본키컬럼 = 테이블2.외래키컬럼 and 조건1, 조건2
*/
-- employees, departments 테이블의 데이터 확인
select EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, DEPARTMENT_ID
from employees;
select * from DEPARTMENTS;
/*
employees테이블과 departments테이블을 조인하여 각 직원이 어떤 부서에서
근무하는지를 출력하시오.
출력결과] 사원아이디, 이름1, 이름2, 이메일, 부서번호, 부서명
*/
-- SQL 표준방식(별칭 사용)
select
employees.employee_id, first_name, last_name, email,
departments.department_id, department_name
from
employees inner join departments
on
employees.department_id = departments.department_id;
-- SQL 표준방식(별칭 사용)
select
emp.employee_id, emp.first_name, emp.last_name, emp.email,
dep .department_id, dep.department_name
from
employees emp inner join departments dep
on
emp.department_id = dep.department_id;
/*
[3개 이상의 테이블을 조인할때]
표준 SQL 방식
select
컬럼1, 컬럼2, .... , 컬럼N
from
테이블1 inner join 테이블2
on 테이블1.기본키컬럼 = 테이블2.외래키컬럼
테이블2 inner join 테이블3
on 테이블2.기본기컬럼 = 테이블3.외래키컬럼
Oracle 방식
select
컬럼1, 컬럼2, .... , 컬럼N
from
테이블1, 테이블2, 테이블3
where
테이블1.기본키컬럼 = 테이블2.외래키컬럼
and
테이블2.기본기컬럼 = 테이블3.외래키컬럼
*/
/*
3개의 테이블 조인
: seattle(시에틀)에 위치한 부서에서 근무하는
직원의 정보를 출력하는 쿼리문을 작성하시오.
출력정보] 사원이름, 이메일, 부서ID, 부서명, 담당업무ID, 담당업무명, 근무지역
*/
select
emp.first_name, emp.last_name, emp.email, emp.department_id, emp.job_id,
dep.department_name,
job.job_title,
loc.city
from
employees emp inner join departments dep
on emp.department_id = dep.department_id
inner join locations loc
on dep.location_id = loc.location_id
inner join jobs job
on emp.job_id = job.job_id
where
loc.city = 'Seattle';
-- Oracle 방식
select
e.first_name, e.last_name, e.email, e.department_id, e.job_id,
d.department_name,
j.job_title,
l.city
from
employees e, departments d, jobs j, locations l
where
l.city = 'Seattle'
and
e.department_id = d. department_id
and
e.job_id = j.job_id
and
d.location_id = l.location_id;
/*
[2] outer join(외부조인)
outer join은 inner join과는 달리 두 테이블에 조인조건이 정확히 일치하지 않더라도
기준이 되는 테이블에서 결과값을 가져오는 join문이다.
outer join문을 사용할때는 반드시 outer전에 데이터를
어느쪽 테이블에서 가져올지 기술해야한다.
left(왼쪽테이블), right(오른쪽테이블), full(양쪽테이블)
[참고] inner join에 비해 outer join의 쿼리처리속도가 느리다.
그래서 join문을 사용해야 한다면 inner join을 사용하는것이 웹어플리케이션의
성능향상에 도움이 된다.
- left outer join
: 조인문의 왼쪽을 중심으로 왼쪽 테이블의 데이터를 모두 가져온다.
- right outer join
: 조인문의 오른쪽을 중심으로 오른쪽 테이블의 데이터를 모두 가져온다.
- full outer join
: 조인문 양쪽에 있는 모든 테이블에서 데이터를 모두 가져온다.
사용법 :
select
컬럼1, 컬럼2, .... , 컬럼N
from
테이블1 left[right, full] outer join 테이블2
on 테이블1.컬럼명 = 테이블2.컬럼명
where
조건1, 조건2, .... , 조건N
*/
-- SQL 표준방식
/* 전체직원의 사원번호, 이름, 부서아이디, 부서명, 지역을 출력하시오. */
select
emp.employee_id, emp.first_name, emp.last_name, emp.department_id,
dep.department_name,
loc.city
from
employees emp left outer join departments dep
on emp.department_id = dep.department_id
left outer join locations loc
on dep.location_id = loc.location_id
where
1 = 1;
/*
Oracle 방식
: outer join 연산자인(+)룰 where절에 붙여준다
*/
/* 전체직원의 사원번호, 이름, 부서아이디, 부서명, 지역을 출력하시오. */
select
e.employee_id, e.first_name, e.last_name,
d.department_id, d.department_name,
l.city, l.state_province
from
employees e, departments d, locations l
where
1 = 1 and e.department_id = d.department_id (+)
and
d.location_id = l.location_id (+);
/*
사원테이블에서 각 사원의 매니저 아이디와 매니저 이름을 출력하시오
여기서 매니저는 직속상관 혹은 상사를 뜻한다.
*/
select
empCrew.employee_id, empCrew.first_name, empCrew.last_name,
empMgr.employee_id "매니저ID", empMgr.first_name "매니저이름1",
empMgr.last_name "매니저이름2"
from
employees empCrew, employees empMgr
where
empCrew.manager_id = empMgr.employee_id
order by
empCrew.employee_id;
/*
1. 하나의 테이블이 각각 사원정보테이블, 매니저정보테이블로 나눠진다.
2. 사원의 매니저 아이디와 매니저의 사원 아이디를 매칭
3. 각각의 테이블 별칭을 이용해서 필요한 정보를 출력한다.
*/
/*
using 사용하기 : join문에서 주로 사용하는 on절을 using으로 대체가능
*/
/* 전체직원의 사원번호, 이름, 부서아이디, 부서명, 지역, 국가명을 출력하시오. */
select
employee_id, first_name, last_name,
department_id, department_name,
city, state_province,
country_id, country_name
from
employees e left outer join departments d
using(department_id)
left outer join locations l
using(location_id)
left outer join countries c
using(country_id)
where 1=1;
/*
using절에 사용된 식별자 department_id, location_id, contry_id의 경우
select절에서 테이블의 식별자를 붙히면 아래와 같은 쿼리 오류발생됨
ORA-25154: USING 절의 열 부분은 식별자를 가질 수 없음
25154. 00000 - "column part of USING clause cannot have qualifier"
using에 사용된 식별자는 좌,우측 테이블에 동시에 존재하는 컬럼이라는것을
전제로 작성하기 때문에 굳이 식별자를 붙힐 이유가 없다.
*/
/*
#조인
Oracle 개인폴더에 “03조인” 문서로 업로드 해주세요.
*/
/*
1. inner join 방식중 오라클방식을 사용하여 first_name 이 Janette 인
사원의 부서ID와 부서명을 출력하시오.
출력목록] 부서ID, 부서명
*/
select
e.first_name, d.department_id,d.department_name
from
employees e, departments d
where
e.department_id = d.department_id and
e.first_name = 'Janette';
/*
2. inner join 방식중 SQL표준 방식을 사용하여 사원이름과 함께 그 사원이
소속된 부서명과 도시명을 출력하시오
출력목록] 사원이름, 부서명, 도시명
*/
select
e.first_name, e.last_name, d.department_name, l.city
from
employees e inner join departments d
on e.department_id = d.department_id
inner join locations l
on d.location_id = l.location_id
where
1=1
;
/*
3. inner join과 using 연산자를 사용하여 50번 부서(DEPARTMENT_ID)에
속하는 모든 담당업무(JOB_ID)의 고유목록을 부서의 도시명(CITY)을 포함하여 출력하시오.
출력목록] 담당업무ID, 부서ID, 부서명, 도시명
*/
select
distinct e.job_id, department_id, d.department_name, l.city
from
employees e
inner join departments d
using(department_id)
inner join locations l
using(location_id)
where
department_id=50;
/*
[주의] using절에 사용된 컬럼명은 join한 양쪽테이블에 동일하게 존재하는 컬럼을
기반으로 하기 때문에 select절이나 where절에 사용할 때는 테이블명 혹은
별칭을 사용하면 쿼리에러가 발생된다.
*/
/*
4. 내부조인을 사용하여 커미션(COMMISSION_PCT)을 받는 모든
사원의 이름, 부서명, 도시명을 출력하시오.
출력목록] 사원이름, 부서ID, 부서명, 도시명
*/
select
emp.first_name, emp.last_name, dep.department_id, dep.department_name, loc.city
from
employees emp, departments dep, locations loc
where
emp.department_id = dep.department_id and
dep.location_id = loc.location_id and
commission_pct is not null
;
/*
5. 사원의 이름(FIRST_NAME)에 'A'가 포함된 모든사원의 이름과 부서명을 출력하시오.
출력목록] 사원이름, 부서명
*/
select
first_name, last_name, department_name
from
employees emp inner join departments dep on emp.department_id=dep.department_id
where first_name like '%A%';
/*
6. “city : Toronto / state_province : Ontario” 에서 근무하는 모든 사원의 이름, 업무명, 부서번호 및 부서명을 출력하시오.
출력목록] 사원이름, 업무명, 부서ID, 부서명
*/
select
e.first_name, e.last_name, j.job_title, d.department_id, d.department_name
from employees e, departments d, locations l, jobs j
where
city = 'Toronto' and state_province='Ontario' and
e.department_id = d.department_id and
d.location_id = l.location_id and
e.job_id = j.job_id
;
/*
7. self join을 사용하여 사원의 이름 및 사원번호를
관리자 이름 및 메니져 번호와 함께 출력하시오.
즉 관리자가 있는 사원만 출력해야 한다.
출력목록] 사원이름, 사원ID, 메니져이름, 메니져아이디
*/
--사원과 매니져 레코드를 확인하기 위한 쿼리문
select employee_id, first_name, last_name, manager_id from employees;
select
Crew.first_name, Crew.employee_id,
Manager.first_name, Manager.employee_id, Crew.manager_id
from
employees Manager , employees Crew
where
Manager.employee_id = Crew.manager_id
order by Crew.employee_id desc
;
/*
8. outer join, self join을 사용하여 관리자가 없는 사원을 포함하여
사원번호를 기준으로 내림차순 정렬하여 출력하시오.
출력목록] 사원이름, 사원ID, 메니져이름, 메니져아이디
*/
select
Crew.employee_id, Crew.first_name,Crew.last_name,
Mgr.employee_id, Mgr.first_name, Mgr.last_name
from
employees Mgr, employees Crew
where
Crew.manager_id = Mgr.employee_id (+)
order by
Crew.employee_id desc;
/*
9. self join을 사용하여 “Timothy / Gates” 사원의 이름, 부서번호
그리고 해당 사원과 동일한 부서에서 근무하는 사원의 이름을 출력하시오.
출력목록] Timothy사원이름과 성, 부서ID, 사원이름과 성
*/
-- 이름이 Timothy 인 사원의 정보출력
select * from employees where first_name ='Timothy' and last_name = 'Gates';
select
Timothy.first_name, Timothy.last_name, Timothy.department_id,
Crew.first_name, Crew.last_name
from
employees Timothy , employees Crew
where
Timothy.department_id = Crew.department_id and
Timothy.first_name = 'Timothy' and
Crew.first_name != 'Timothy'
;
/*
Timothy의 동료가 Timothy일 수는 없으므로 사원의 이름이 Timothy인
레코드 하나를 제외시켜야 한다.
*/
/*
10. self join을 사용하여 “Kimberely / Grant” 사원보다 늦게 입사한
사원의 이름과 입사일을 출력하시오.
출력목록] 사원이름, 입사일
*/
select * from employees where first_name='Kimberely';
select
Crew.first_name, Crew.last_name, Crew.hire_date
from
employees Kimberely, employees Crew
where
Kimberely.first_name='Kimberely' and
Kimberely.hire_date < Crew.hire_date
order by Crew.hire_date asc
;
/*
11. self join을 사용하여 메니져보다 먼저 입사한 사원의 정보를 출력하시오.
사원의 이름과 입사일, 메니져의 이름과 입사일을 출력하도록 한다.
출력목록] 사원이름, 사원입사일, 메니져이름, 메니져입사일
*/
select
crew.first_name, crew.last_name, crew.hire_date 사원입사일,
mgr.first_name, mgr.last_name, mgr.hire_date 매니저입사일
from
employees mgr, employees crew
where
mgr.employee_id = crew.manager_id
and
mgr.hire_date < crew.hire_date
;
'프로그래밍 > Oracle' 카테고리의 다른 글
Or10DML (0) | 2017.11.15 |
---|---|
Or09DDL (0) | 2017.11.15 |
Or06GroupBy (0) | 2017.11.15 |
Or05Date (0) | 2017.11.15 |
Or04TypeConvert (0) | 2017.11.15 |