1. 서브 쿼리
서브 쿼리는 '쿼리 안에 쿼리' 라는 뜻이다.
서브쿼리는 사전에 추출된 내용에서 재 검색 하거나, 검색된 내용을 가상 컬럼을 만들어 추가 할 수 있다.
-- 서브 쿼리 : 쿼리 안의 쿼리
-- 하나의 쿼리문으로 받아온 데이터를 바탕으로 다른 내용을 검색할 때 사용
-- 1. 추출된 결과로 다른 내용을 검색 시 사용
-- 2. 검색된 내용을 가상의 컬럼으로 볼 때 사용
create table dept(
deptno varchar(10) primary key
,deptname varchar(20)
,loc varchar(10)
);
create table emp(
ename varchar(20)
,job varchar(50)
,deptno varchar(10)
,hiredate date
);
alter table emp add constraint foreign key(deptno) references dept(deptno);
insert into dept(deptno, deptname, loc) values('1', 'sales', 'newyork');
insert into dept(deptno, deptname, loc) values('2', 'dev01', 'la');
insert into dept(deptno, deptname, loc) values('3', 'personnel', 'newyork');
insert into dept(deptno, deptname, loc) values('4', 'delevery', 'boston');
select * from dept;
insert into emp(ename, job, deptno, hiredate)
values('kim', 'manager', '1', str_to_date('16/01/02', '%Y/%m/%d'));
insert into emp(ename, job, deptno, hiredate)
values('lee', 'staff', '1', str_to_date('15/01/02', '%Y/%m/%d'));
insert into emp(ename, job, deptno, hiredate)
values('han', 'staff', '1', str_to_date('16/03/02', '%Y/%m/%d'));
insert into emp(ename, job, deptno, hiredate)
values('kim', 'assistant', '1', str_to_date('15/09/22', '%Y/%m/%d'));
insert into emp(ename, job, deptno, hiredate)
values('ahn', 'staff', '2', str_to_date('15/11/02', '%Y/%m/%d'));
insert into emp(ename, job, deptno, hiredate)
values('hwang', 'manager', '2', str_to_date('15/08/02', '%Y/%m/%d'));
insert into emp(ename, job, deptno, hiredate)
values('cha', 'assistant', '2', str_to_date('12/03/02', '%Y/%m/%d'));
insert into emp(ename, job, deptno, hiredate)
values('hong', 'staff', '2', str_to_date('14/08/02', '%Y/%m/%d'));
insert into emp(ename, job, deptno, hiredate)
values('gang', 'staff', '2', str_to_date('10/01/02', '%Y/%m/%d'));
insert into emp(ename, job, deptno, hiredate)
values('name', 'leader', '4', str_to_date('10/01/02', '%Y/%m/%d'));
select * from emp;
-- 문제1 > 'han' 의 근무 부서명은?
-- emp 테이블에서 han 의 deptno 를 알아낸다.
select deptno from emp where ename = 'han';
-- deptno 를 통해 dept 의 deptname 을 알아낸다.
select deptname from dept where deptno = '1';
-- 해결
select deptname, loc from dept where deptno = (select deptno from emp where ename = 'han');
-- 문제2 > 부서 위치가 'la' 또는 'boston' 인 부서 소속의 사람들의 이름, 직책은?
select ename, job from emp where deptno in (select deptno from dept where loc in('la', 'boston'));
-- 문제3 > sales 부서에 근무하는 사원 데이터(ename, job, hiredate) 가져오기
select deptno from dept where deptname = 'sales';
select ename, job, hiredate from emp where deptno = '1';
select ename, job, hiredate from emp where deptno = (select deptno from dept where deptname = 'sales');
-- 문제4 > 직책(job)이 manager 인 사원들(여러명 일 경우 빠른 직원 기준)보다 입사일이 빠른 직원(ename, job, hiredate)은?
select * from emp order by hiredate asc;
select * from emp where job = 'manager' order by hiredate asc limit 1;
select ename, job, hiredate from emp
where hiredate < (select min(hiredate) from emp where job = 'manager') order by hiredate;
-- 문제5 > 부서별(deptno, deptname)로 직원이 몇명인지 확인
select * from dept; -- 1, 2, 3, 4
select count(deptno) from emp where deptno = 1; -- 4
select count(deptno) from emp where deptno = 2; -- 5
select count(deptno) from emp where deptno = 4; -- 1
select deptno, deptname from dept where deptno = 1;
select deptno, deptname from dept where deptno = 2;
select deptno, deptname from dept where deptno = 4;
-- 상하 관계 쿼리
-- 서브쿼리의 결과물이 본 쿼리의 일부로 사용될 경우
-- 서브쿼리의 내용이 메인 쿼리의 일부가 되는 것
-- 컬럼, 테이블로 활용이 된다.
select deptno, deptname, (select count(deptno) from emp where deptno = 1) as cnt from dept where deptno = 1;
select deptno, deptname, (select count(deptno) from emp where deptno = 2) as cnt from dept where deptno = 2;
select deptno, deptname, (select count(deptno) from emp where deptno = 4) as cnt from dept where deptno = 4;
-- 해결 >
select deptno, deptname, (select count(deptno) from emp where deptno = d.deptno) as cnt
from dept d; -- dept 'd' -> 별칭
-- group by 사용
select deptno, count(deptno) as cnt from emp group by deptno;
select deptno,
(select deptname from dept where deptno = emp.deptno) as deptname,
count(deptno) as cnt
from emp group by deptno;
2. JOIN
-- JOIN 이란?
-- 둘 이상의 테이블을 연결하여 데이터를 검색하는 방법 이다.
-- 두개의 테이블이 조인하기 위해서는 적어도 하나의 공통된 컬럼이 존재 해야 한다.
-- 그래서 일반적으로 부모(PK)와 자식(FK)간에 조인이 수월하게 이루어 진다.
-- JOIN 의 종류
-- CROSS JOIN, EQUI JOIN(등가조인, 내부조인)
-- NON-EQUI JOIN(거의 안쓰이기 때문에 다루지 않음)
-- SELF JOIN, OUTER JOIN
-- 0. CROSS JOIN
-- 두개의 테이블을 카다시안 곱을 수행한다.
-- emp(10) * dept(4) = 40
-- FROM [tableA] CROSS JOIN [tableB]
select e.ename,d.deptname from emp e cross join dept d;
-- cross join 은 생략 가능
select e.ename,d.deptname from emp e, dept d;
-- cross join 은 아직 정제되지 않은 순수한 조인 형태
-- 그래서 조건을 주어서 원하는 데이터를 뽑아낸다.
-- 1. Equi Join - 조인 하는 두 테이블 모두에 값이 있을 떄만 보여준다.
-- 가장 일반적으로 사용하는 조인(= 를 사용)
-- 1) 등가 조인
select e.ename,d.deptname from emp e, dept d where e.deptno = d.deptno;
insert into dept(deptno,deptname,loc)values('5','dev02','florida');
/* 양쪽에 데이터 불균형이 있을 경우
* ename, deptname
* (NULL), personnel
* (NULL), dev02
* 이런식으론 보여주지 않음
*/
-- 2) 내부 조인
-- FROM [tableA] INNER JOIN [tableB]
-- inner 생략 가능, 조인을 위한 조건은 where 가아닌 on을 사용
select e.ename,d.deptname from emp e join dept d on e.deptno = d.deptno;
-- using 을 사용하여 조건을 줄 수 있다.
-- using(서브쿼리) 가 가능 하다.
select e.ename,d.deptname from emp e join dept d using (deptno);
-- 3) 네츄럴 조인
-- 네츄럴 조인은 두 테이블 사이 공통되는 컬럼이 있으면 자연스럽게 합쳐지게 된다.
-- 그래서 조인을 위한 조건절이 필요 없다.
-- 주의사항 : 공통되는 컬럼명은 단축명을 사용하지 않는다.(일부 DB 에서 에러 날 수 있음)
select deptno, e.ename,d.deptname from emp e natural join dept d;
-- 2. 셀프조인
-- Equi-Join 과 똑같다. 다만 두개의 테이블이 둘다 자신이라는 것만 다르다.
-- 셀프조인을 하면 두 데이터간 카다시안 곱을 수행 한다.
select a.ename,b.job from emp a, emp b where a.deptno = b.deptno;
-- 3. 외부조인
-- [tableA] [left|right] outer join [tableB] ON 조건절
-- LEFT (왼쪽을 기준으로 더 있는 값을 보여줌)
-- RIGHT(오른쪽을 기준으로 더 있는 값을 보여줌)
-- FULL (서로 없는 값을 보여줌)
-- outer 는 생략 가능
select d.deptno, e.ename, d.deptname
from emp e right outer join dept d on e.deptno = d.deptno;
-- emp 에 deptno 6번을 추가
insert into emp(deptno,ename,job, hiredate)values('6','kim','assistant',str_to_date('14-06-02','%Y-%m-%d'));
-- 연계참조 무결성 제약조건에 의해서 부모(dept) 에게 없는 6번을 자식(emp)이 넣을 수 없다.
-- 그래서 부모-자식 관계를 해제 -> FK 를 삭제
select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME = 'emp';
alter table emp drop constraint emp_ibfk_1;
select * from emp;
select e.deptno, e.ename, d.deptname
from emp e left join dept d on e.deptno = d.deptno;
/* left join : join 을 기준으로 왼쪽 테이블의 데이터를 기준으로 보여준다.(오른쪽에 없는 내용은 null 처리) - 1,2,4,6
* right join : join 을 기준으로 오른쪽 테이블의 데이터를 기준으로 보여준다.(왼쪽에 없는 내용은 null 처리) - 1,2,3,4,5
* 서로 없는 내용을 보여줄수 있는 방법 : full outer join
* */
4. SET
-- 다수의 테이블을 집합 연산 할 수 있다.
-- 합집합(UNION, UNION ALL), 교집합(INTERSECT), 차집합(MINUS)이 존재 한다.
-- 중복 제거를 해 주는 UNION 은 성능저하 문제로 권장하지 않는다.
-- [qry1] [UNION | UNION ALL | INTERSECT| MINUS] [qry2]
-- 1. UNION : 중복을 제거한 합집합
select deptno from emp
union
select deptno from dept order by deptno;
-- left join 과 right join 을 union 하면 full outer join 효과를 얻을 수 있다.
select e.deptno, e.ename, d.deptname from emp e left join dept d on e.deptno = d.deptno
union
select d.deptno, e.ename, d.deptname from emp e right join dept d on e.deptno = d.deptno;
-- 2. UNION ALL : 중복제거 없이 합집합 실행
-- UNION ALL 을 순수하게 실행한다기 보다는 정제해서 사용 한다.
select deptno from emp
union all
select deptno from dept order by deptno;
-- 3. INTERSECT : 양 테이블에 존재하는 중복된 데이터만 확인 한다.
select deptno from emp
intersect
select deptno from dept order by deptno;
-- 4. MINUS : 마리아디비에서는 차집합 지원하지 않는다.
select distinct deptno from emp; -- 1,2,4,6
select distinct deptno from dept; -- 1,2,3,4,5
-- emp - dept = 6
select deptno from emp where deptno not in (select deptno from dept);
-- dept - emp = 3, 5
select deptno from dept where deptno not in (select deptno from emp);
-- emp 와 dept 를 합집합한 내용을 emp 와 교집합
select deptno from emp
union
select deptno from dept
intersect
select deptno from emp;
-- union 을 대체할 경우?
-- 1. 일단 합친다.
-- 2. 합친 내용을 가지고 중복 제거
select distinct u.deptno from
(select deptno from emp
union all
select deptno from dept) u order by u.deptno asc;
'DB' 카테고리의 다른 글
| 06. 정규화 (Normalization) (2) | 2024.02.27 |
|---|---|
| 05. DB 기능 (auto_increment, limit 등) (2) | 2024.02.27 |
| 04. INDEX, EXISTS, VEIW (0) | 2024.02.27 |
| 02. Constraint과 Relation (0) | 2024.02.27 |
| 01. DB의 기초 (0) | 2024.02.27 |