오늘의 요약
SQL> select DEPTNO, round(avg(SAL)) from EMP
where SAL>=2000 group by DEPTNO order by round(avg(SAL)) desc;
SQL> select DEPTNO, round(avg(SAL)) aa from EMP
where SAL>=2000 group by DEPTNO order by aa desc;
SQL> select DEPTNO, round(avg(SAL)) from EMP
where SAL>=2000 group by DEPTNO order by 2 desc;
SQL> select DEPTNO, round(avg(SAL)) from EMP
where SAL>=1000
group by DEPTNO
having round(avg(SAL))>=2000
order by DEPTNO desc;
Err> select DEPTNO, round(avg(SAL)) aa from EMP
where SAL>=1000
group by DEPTNO
having aa>=2000
order by DEPTNO desc;
SQL> select DEPTNO, JOB, count(EMPNO) from EMP
group by DEPTNO, JOB
order by DEPTNO desc, JOB desc;
< 일반화 >
[1] 순서 ( SF - WGHO )
select -> from -> where -> group by -> having -> order by
[2] where 절에는 그룹함수를 사용 불가
[3] having 절에서는 alias를 사용할 수 없음
1) 설명
하나의 테이블로는 원하는 컬럼정보를 참조할 수
없는 경우 관련된 테이블을 '논리적으로 결합'하여
원하는 컬럼정보를 참조하는 방법을 '조인'이라 한다.
2) 조건
논리적으로 결합되는 2개 이상의 테이블에는 반드시
'공통컬럼'이 존재해야하며 이 '공통 컬럼'은
동일한 데이터 타입과 공통된 데이터를 포함해야 한다.
3) 일반적인 조인예
<1> NATURAL 조인 ( EQUI 조인 )
select EMP.EMPNO, DEPT.DNAME from EMP, DEPT where EMP.DEPTNO=DEPT.DEPTNO;
select e.EMPNO, d.DNAME from EMP e, DEPT d where e.DEPTNO=d.DEPTNO;
select e.EMPNO, d.DNAME from EMP e join DEPT d on e.DEPTNO=d.DEPTNO;
select EMP.EMPNO, DEPT.DNAME from EMP join DEPT using(DEPTNO);
select EMPNO, DNAME from EMP natural join DEPT;
< 문제 >
SQL> select EMP.EMPNO, DEPT.DNAME from EMP, DEPT
where EMP.DEPTNO=DEPT.DEPTNO and EMP.EMPNO=7900;
SQL> select e.EMPNO, d.DNAME from EMP e, DEPT d
where e.DEPTNO=d.DEPTNO and e.EMPNO=7900;
SQL> select e.EMPNO, d.DNAME from EMP e join DEPT d
on e.DEPTNO=d.DEPTNO and e.EMPNO=7900;
SQL> select e.EMPNO, d.DNAME from EMP e join DEPT d
on e.DEPTNO=d.DEPTNO where e.EMPNO=7900;
SQL> select EMP.EMPNO, DEPT.DNAME from EMP join DEPT using(DEPTNO)
where EMP.EMPNO=7900;
SQL> select EMPNO, DNAME from EMP natural join DEPT
where EMPNO=7900;
< 일반화: DQL의 배치순서와 실행순서 >
- select XX
- from XX
- (join XX)
- where XX
- group by XX
- having XX
- order by XX
<2> SELF 조인
< 문제 >
SQL> select e.ENAME||'의 매니져는 ', m.ENAME||'이다'
from EMP e, EMP m where e.MGR=m.EMPNO;
SQL> select e.ENAME||'의 매니져는 ', m.ENAME||'이다'
from EMP e, EMP m where e.MGR=m.EMPNO and e.ENAME='JAMES';
SQL> select e.ENAME||'의 매니져는 ', m.ENAME||'이다'
from EMP e join EMP m on e.MGR=m.EMPNO
where e.ENAME='JAMES';
1) 설명
하나의 DQL문장절에 부속된(포함된) 또 다른 SELECT문장
따라서, 두 번 이상 질의를 해야 얻을 수 있는 결과를
한번의 질의로 해결이 가능케하는 쿼리
2) 용어
[1] MAIN-QUERY or OUTER-QUERY
[2] SUB-QUERY or INNER-QUERY
3) 특징
[1] 괄호를 묶어야 한다.
[2] 실행순서는 '대부분' SUB-QUERY가 먼저 수행되고,
MAIN-QUERY가 실행된다.
[3] SUB-QUERY는 MAIN-QUERY의 다음 부분에 위치된다.
- SELECT/DELETE/UPDATE문장의 FROM절/WHERE절
- INSERT문장의 INTO절
- UPDATE문장의 SET절
[4] SUB-QUERY는 ORDER BY절을 사용할 수 없다.
(예외 : SELECT/DELETE/UPDATE문장의 FROM절 )
4) 종류
[1] 단일행 SUB-QUERY
-> SUB-QUERY의 실행결과가 '하나의 컬럼' AND
'하나의 행'만을 리턴해 주는 경우의 쿼리
즉, '하나의 데이터'를 리턴해 주는 쿼리
< 문제 >
Join> select e.EMPNO, d.DNAME from EMP e, DEPT d
where e.DEPTNO=d.DEPTNO and e.EMPNO=7900;
Sub> select DEPTNO from EMP where EMPNO=7900;
Main> select DNAME from DEPT where DEPTNO=?;
SQL> select DNAME from DEPT
where DEPTNO=(select DEPTNO from EMP where EMPNO=7900);
Sub> select SAL from EMP where DEPTNO=10;
Main> select ENAME, COMM from EMP where SAL=?
Err> select ENAME, COMM from EMP
where SAL=(select SAL from EMP where DEPTNO=10);
Sub> select SAL, COMM from EMP where EMPNO=7369;
Main> select ENAME, SAL, COMM from EMP where SAL=?;
Err> select ENAME, SAL, COMM from EMP
where SAL=(select SAL, COMM from EMP where EMPNO=7369);
Err> select ENAME, SAL from EMP where SAL>avg(SAL);
Sub> select avg(SAL) from EMP;
Main> select ENAME, SAL from EMP where SAL>?
SQL> select ENAME, SAL from EMP where SAL>(select avg(SAL) from EMP);
[2] 복수행 SUB-QUERY
-> SUB-QUERY의 실행결과가 '여러개의 행'을 return 하는 경우의 쿼리
( 연산자를 이용: in[=any], any, exists, all )
<1> in
Sub> select SAL from EMP where DEPTNO=10;
Main> select ENAME, SAL from EMP where SAL=?
Err> select ENAME, SAL from EMP where SAL=(select SAL from EMP where DEPTNO=10);
SQL> select ENAME, SAL from EMP
where SAL in (select SAL from EMP where DEPTNO=10);
SQL> select ENAME, SAL from EMP
where SAL=any(select SAL from EMP where DEPTNO=10);
효과> select ENAME, SAL from EMP
where SAL=2450 or SAL=5000 or SAL=1300;
<2> all
Sub> select SAL from EMP where JOB='MANAGER';
Main> select JOB,SAL from EMP where SAL>=?;
SQL> select JOB,SAL from EMP
where SAL>=(select max(SAL) from EMP where JOB='MANAGER');
SQL> select JOB,SAL from EMP
where SAL>=all(select SAL from EMP where JOB='MANAGER');
효과> select JOB,SAL from EMP
where SAL>=2975 and SAL>=2850 and SAL>=2450;
<3> any
Sub> select SAL from EMP where JOB='SALESMAN';
Main> select JOB,SAL from EMP where SAL<?;
SQL> select JOB,SAL from EMP
where SAL<any(select SAL from EMP where JOB='SALESMAN');
효과> select JOB,SAL from EMP
where SAL<1600 or SAL<1250 or SAL<1500;
<4> exists
Sub> select * from EMP where DEPTNO=10;
Main> select DNAME from DEPT
where exists(select * from EMP where DEPTNO=10);
[3] 복수 컬럼 SUB-QUERY
-> SUB-QUERY의 실행결과가 여러개의 '컬럼을 값'
(AND 여러개의 행)을 리턴해 주는 쿼리
Sub> select SAL, COMM from EMP where DEPTNO=30;
Main> select ENAME, DEPTNO from EMP
where (SAL, COMM)
in (select SAL, COMM from EMP where DEPTNO=30);
비교> select ENAME, DEPTNO from EMP
where (SAL, nvl(COMM,0))
in (select SAL, nvl(COMM,0) from EMP where DEPTNO=30);
[4] 상호 관련 SUB-QUERY
-> MAIN-QUERY절에 사용된 테이블이 SUB-QUERY절에 다시
재사용되는 경우의 서브쿼리
Sub> select avg(e1.SAL) from EMP e1, EMP e2
where e1.DEPTNO=e2.DEPTNO;
Sub-Err> select avg(SAL) from EMP e2
where e1.DEPTNO=e2.DEPTNO;
Main> select e1.EMPNO, e1.SAL from EMP e1
where SAL>(select avg(SAL) from EMP e2
where e1.DEPTNO=e2.DEPTNO);
cf) 연습문제
SQL> select e.EMPNO, d.DNAME from EMP e, DEPT d
where e.DEPTNO=d.DEPTNO and e.EMPNO=7900;
SQL> select DNAME from DEPT
where DEPTNO=(select DEPTNO from EMP where EMPNO=7900);
Sub> select avg(SAL) from EMP where DEPTNO=10;
Main> select ENAME, SAL from EMP where SAL<?;
SQL> select ENAME, SAL from EMP
where SAL<(select avg(SAL) from EMP where DEPTNO=10);
SQL> select ENAME, SAL from EMP
where SAL<(select avg(SAL) from EMP where DEPTNO=10)
order by SAL desc;
Sub> select avg(SAL) from EMP where DEPTNO=10;
Main> select DEPTNO, round(avg(SAL)) from EMP
where SAL< ?
group by DEPTNO
having DEPTNO != 10
order by DEPTNO desc;
SQL> select DEPTNO, round(avg(SAL)) from EMP
where SAL< (select avg(SAL) from EMP where DEPTNO=10)
group by DEPTNO
having DEPTNO != 10
order by DEPTNO desc;