1. select문의 6가지 절
select
보고싶은 컬럼명from
테이블명where
검색조건group by
그룹핑할 컬럼having
그룹핑할 컬럼으로 검색조건order by
정렬할 컬럼
2. 함수
- 단일행함수 :
문자, 숫자, 날짜, 변환, 일반
- 복수행 함수 :
max, min, avg, sum, count
- 데이터 분석함수 :
rank, dense_rank, ntile, cume_dist, listagg, lag, lead, 누적데이터 구하기 , 기타
3. 조인
- 오라클 조인 문법
1. equi jion
2. non equi jion
3. outer join
4. self join
- 1999 ANSI (미국 국립 표준 협회)조인문법 (10g)
1. on절을 사용한 조인
2. using 절을 사용한 조인
3. left / right / full outer join
4. natural join
5. cross join
자기 자신과 조인하는 조인문법!
select empno, ename, mgr
from emp;
예제. 사원이름, 자기 자신의 관리자를 출력
select 사원.ename, 관리자.ename
from emp 사원, emp 관리자
where 사원.mgr = 관리자.empno;
where 사원.mgr = 관리자.empno;
문제 318. 사원이름, 관리자이름을 출력하는데 사원이름이 smith인 사원만 출력하시오
select 사원.ename, 관리자.ename from emp 사원, emp 관리자 where 사원.mgr = 관리자.empno and 사원.ename = 'SMITH';
문제 320. 사원이름, 관리자 이름을 출력하는데 관리자보다 월급이 더 많은 사원들만 출력
select e.ename as 사원이름, m.ename as 관리자이름 from emp e, emp m where e.mgr = m.empno and m.sal < e.sal;
문제 321. 사원이름, 사원의 입사일, 관리자 이름, 관리자의 입사일을 출력하는데 관리자보다 먼저 입사한 사원들만 출력
select e.ename as 사원이름, e.hiredate as 사원입사일, m.ename as 관리자이름, m.hiredate as 관리자입사일 from emp e, emp m where e.mgr = m.empno and m.hiredate > e.hiredate;
문제 322. (OCP 시험) HR계정(유저)의 employees 테이블을 이용해서 self join을 하는데, 관리자 번호가 100번인 사원의 사원이름과 관리자 이름을 출력하시오 !
select e.last_name, m.last_name, e.manager_id from employees e , employees m where e.manager_id = m.employee_id and e.manager_id = 100;
1999 ansi 조인문법(on절 사용한 조인)
// * on절을 사용한 ansi문법! *
select e.last_name, m.last_name, e.manager_id
from employees e join employees m
on e.manager_id = m.employee_id
where e.manager_id = 100;
// * 오라클 문법! *
select e.last_name, m.last_name, e.manager_id
from employees e , employees m
where e.manager_id = m.employee_id -> 조인조건
and e.manager_id = 100; -> 검색조건
문제 323. 이름, 부서위치를 출력하는데 on절을 사용한 조인 문법으로 구현하시오!
select d.loc, e.ename from dept d join emp e on (e.deptno = d.deptno); // 가급적 괄호 써주기!
문제 324. on절을 사용한 조인문법으로, DALLAS에서 근무하는 사원들의 이름, 부서위치 출력
select d.loc, e.ename from dept d join emp e on (e.deptno = d.deptno) where d.loc = 'DALLAS';
문제 325. 직업이 SALESMAN인 사원들의 이름, 직업, 부서위치를 출력하시오
select e.ename, e.job, d.loc from dept d join emp e on (e.deptno = d.deptno) where e.job = 'SALESMAN';
1. equi join , 2. non equi join, 3. outer join, 4. self join
문제 326. (복습) emp와 salgrade를 조인해서, 이름, 월급, 급여등급(grade)를 출력하는데 3등급만 출력하시오 (non equi join)
오라클
select e.ename, e.sal, s.grade from emp e , salgrade s where e.sal between s.losal and s.hisal and s.grade = 3;
on절 사용
select e.ename, e.sal, s.grade from emp e join salgrade s on (e.sal between s.losal and s.hisal) where s.grade = 3;
문제 327. (3개의 테이블 조인) emp, dept, salgrade를 조인해서 급여등급인 3등급인 사원들의 이름, 월급, 부서위치, 등급 출력
오라클 join문법
select e.ename, e.sal, d.loc, s.grade from emp e, dept d, salgrade s where e.sal between s.losal and s.hisal and e.deptno = d.deptno and s.grade = 3;
on절 사용
select e.ename, e.sal, d.loc, s.grade from emp e join dept d on (e.deptno = d.deptno ) join salgrade s on (e.sal between s.losal and s.hisal) where s.grade = 3;
- on절 사용한 3개이상 join은 from절에 join + join조건인 on 을 함께 써준다!
문제 328. (OCP문제) HR유저의 employees와 departments와 jobs를 조인해서 last_name, department_name, job_title 출력하기
select e.last_name, d.department_name, j.job_title from employees e join departments d on (e.department_id = d.department_id) join jobs j on (e.job_id = j.job_id);
B
예제. 이름, 부서위치를 출력하는데 using 절을 사용한 조인으로 수행
select e.ename, d.loc
from emp e join dept d
using (deptno);
※ 설명! using 절에 연결고리가 되는 컬럼인 deptno 만 작성하면 됨. 주의사항은, e.deptno
또는 d.deptno
라고 하면 에러가 발생
한다.
※ using절
은 조인조건이 이퀄조건이었던 equi join만 가능
하고, between ...and 로 주었던 non equi join은 구현할 수 없다!!!
select e.ename, e.sal, s.grade
from emp e join salgrade
using (?) ; // 뭘 넣을수가 없음!!!!!!!!!!!
문제 329. employees , departments테이블을 조인해서 last_name, department_name을 출력하는데 using절 사용
select e.last_name, d.department_name from employees e join departments d using (department_id);
예제. 이름, 부서위치를 출력하는데 natural join으로 수행하세요!
select e.ename, d.loc
from emp e natural join dept d;
emp e natural join dept d;
문제 330. 부서위치, 부서위치별 토탈월급을 출력하시오 (시험때 두개가 다를것이다.. 하나가 에러날 것이다.. 이런식으로 나온다.)
- 오라클 조인 문법(equi join)
select d.loc , sum(e.sal) from emp e, dept d where e.deptno = d.deptno group by d.loc;
- ansi 문법 (using절)
select d.loc , sum(e.sal) from emp e join dept d using (deptno) group by d.loc;
- ansi 문법 (natural join절)
select d.loc , sum(e.sal) from emp e natural join dept d group by d.loc;
- 출력결과 (3개 모두 동일!)
select d.loc, listagg(e.ename || '(' || e.sal || ')' || ',') within group (order by e.sal desc) from dept d , emp e where e.deptno = d.deptno and d.loc != 'BOSTON' group by d.loc;
예제. 이름, 부서위치를 출력하는데 아우터조인을 사용해서 사원테이블에는 없는 부서번호인데 부서 테이블에는 있는 부서번호에 대한 부서위치를 출력하시오
1. 오라클 조인 문법
select e.ename, d.loc
from emp e, dept d
where e.deptno(+) = d.deptno;
NULL값..!
쪽에 (+) 써주기)2. ANSI문법
select e.ename, d.loc
from emp e right outer join dept d
on (e.deptno = d.deptno);
right outer join
사용.3. 오라클 조인 문법
select e.ename, d.loc
from emp e, dept d
where e.deptno= d.deptno(+);
4. ANSI문법
select e.ename, d.loc
from emp e left outer join dept d
on (e.deptno = d.deptno);
left outer join
를 사용해준다.문제 331. HR유저의 employees, departments 테이블을 조인해서 last_name, department_name 을 출력하는데 부서테이블에는 존재하는 department_name인데 해당 사원이 아직 배치되지 않은 부서명도 출력하세요.
select e.last_name, d.department_name from employees e right outer join departments d on (e.department_id = d.department_id);
- 나는 on 말고 using (department_id); 썼음!
문제 332. SQLD) 위결과에서 last_name이 null인 값들을 맨 위로 출력
select e.last_name, d.department_name from employees e right outer join departments d on (e.department_id = d.department_id) order by e.last_name nulls first;
- 여기서는 using절을 쓰면 에러가난다.
문제 333. (self join) 사원이름, 관리자인 사원의 이름을 출력하기 (on절 사용한 조인문법)
ANSI 문법(ON절)
select e.ename, m.ename from emp e join emp m on (e.mgr = m.empno);
참고! - 오라클 조인문법
select e.ename, m.ename from emp e, emp m where e.mgr = m.empno;
문제 334. (OCP시험) 위 결과에서 사원이름쪽에 KING이 나오게 하세요!
select e.ename, m.ename from emp e left outer join emp m on (e.mgr = m.empno);
- KING의 mgr번호가 null이라서, inner join으로는 출력되지 않는다.
사원이름쪽은 왼쪽이니까left outer join
을 사용했다!
예제. 아래의 오라클 조인 문법이 수행되는지 확인하시오
select e.ename, d.loc from emp e, dept d where e.deptno(+) = d.deptno(+);
위와같은 에러가 발생한다. ANSI문법으로는 가능하다!select e.ename, d.loc from emp e full outer join dept d on (e.deptno = d.deptno);
문제 335. 위 sql의 실행계획 확인하기
explain plan for select e.ename, d.loc from emp e full outer join dept d on (e.deptno = d.deptno); // 하나씩 select * from table(dbms_xplan.display); // 실행!
- 이렇게 나온다면 잘 나온 것. full outer join 은 속도를 많이 느려지게 할 수 있어서
조인(join)
--> 두 테이블의 결과를 양옆으로 연결해서 보여주는 문법
집합연산자
--> 두 테이블의 결과를 위아래로 연결해서 보여주는 문법
문제 336. union) 부서번호, 부서번호별 토탈월급을 출력하시오!
select deptno , sum(sal) from emp group by deptno;
문제 337. 사원테이블의 전체 토탈월급을 출력하시오
select sum(sal) from emp;
문제 338. 롤업을 이용해서 부서번호, 부서번호별 토탈월급을 출력하는데 맨 밑에 전체 토탈월급이 출력되게 하시오
select deptno , sum(sal) from emp group by rollup(deptno);
문제 339. 위 결과를 rollup을 이용하지 않고 union all로 구현해보기
select deptno as 부서번호, sum(sal) as 토탈값 from emp group by deptno union all select to_number(null) as deptno, sum(sal) from emp order by 부서번호 asc;
- 합집합 연산자 사용할 때 주의사항!
- 위의 SQL과 아래의 SQL의 컬럼의 갯수가 동일해야 합니다. (UNION ALL 기준 위, 아래)
- 위의 SQL과 아래의 SQL의 컬럼의 유형이 동일해야 합니다. (문자형인지, 숫자형인지..)
-> NULL값을 TO_NUMBER로 바꿔주었다!- 가급적 컬럼명도 동일하게 해줘야 ORDER BY 할 때 깔끔하게 정렬됩니다.
- ORDER BY절은 맨 아래에 있는 쿼리문에서만 사용 가능합니다.
- 컬럼 별칭은 맨 위 쿼리문에서 정한걸로 사용가능!
문제 340. 아래의 sql을 union all로 구현하시오!
select deptno, job, sum(sal)
from emp
group by grouping sets ((deptno),(job));
select deptno, to_char(null) as job, sum(sal) from emp group by deptno union all select to_number(null) as deptno, job, sum(sal) from emp group by job;
문제 341. 아래의 SQL결과를 union all 로 수행
select to_char(hiredate, 'RRRR'), job, sum(sal)
from emp
group by grouping sets ((to_char(hiredate, 'RRRR')),(job));
select to_char(hiredate, 'RRRR'), to_char(null) as job, sum(sal) from emp group by to_char(hiredate, 'RRRR') union all select to_char(null) , job, sum(sal) from emp group by job;
문제 342. 아래와 같이 년도가 정렬되어 출력되게 만드세요.
select to_char(hiredate, 'RRRR'), to_char(null) as job, sum(sal) from emp group by to_char(hiredate, 'RRRR') union all select to_char(null), job, sum(sal) from emp group by job order by 1 asc; // asc 생략가능
별칭사용
select to_char(hiredate, 'RRRR') as 년도 , to_char(null) as 직업, sum(sal) from emp group by to_char(hiredate, 'RRRR') union all select to_char(null) as 년도, job , sum(sal) from emp group by job order by 1 asc;
문제 343. 아래와 같이 결과를 출력하시오! (직업도 정렬되게 만들기!)
select to_char(hiredate, 'RRRR') as 년도 , to_char(null) as 직업, sum(sal) from emp group by to_char(hiredate, 'RRRR') union all select to_char(null) as 년도, job as 직업 , sum(sal) from emp group by job order by 년도 asc , 직업 asc;
문제 344. 부서번호가 10, 20 번인 사원들의 부서번호, 부서번호별 토탈월급 출력
select deptno, sum(sal)
from emp
where deptno in(10,20)
group by deptno;
문제 345. 부서번호가 20, 30번인 사원들의 부서번호, 부서번호별 토탈월급을 출력하시오
select deptno, sum(sal) from emp where deptno in(20,30) group by deptno;
문제 346. 문제 344번의 결과, 345번의 결과를 위아래로 연결해서 출력하세요(union all)
select deptno, sum(sal) from emp where deptno in(10,20) group by deptno union all select deptno , sum(sal) from emp where deptno in(20,30) group by deptno;
- 사진처럼 union all을 기준으로 위 결과, 아래결과를 그냥 다 가져온다.
문제 347. 위 결과를 union
으로 수행하기
select deptno, sum(sal) from emp where deptno in(10,20) group by deptno union select deptno , sum(sal) from emp where deptno in(20,30) group by deptno;
- 만약, 굳이 중복행을 제거하지 않아도 되고 정렬을 할 필요가 없다면 union 보다는 union all을 사용하는것이 성능상 더 좋다! (기억할것!)
문제 348. (OCP 시험)
A. UNION ALL은 정렬되서 결과가 나오지 않는다.
B. 위아래 컬럼이름은 동일하지 않아도 괜찮다. (데이터 유형은 맞아야함)
C. 셀렉절의 컬럼의 갯수는 위아래가 동일해야한다. -> 답
D. UNION ALL은 중복이 자동으로 제거되지 않는다.
E. null은 체크가 불가해서 중복가능할 때 무시된다. -> 답
select nvl(comm, 9000)
from(
select comm
from emp
where empno in (7566, 7654, 7499)
union
select comm
from emp
where empno in (7499, 7844, 7900)
);
문제 348. 다음과 같이 결과를 출력하세요!
( 직업별 부서번호별 토탈월급들을 출력하는데, 맨 옆과 맨 아래에 집계값들이 같이 출력)
내 답
select nvl(직업,'토탈'), "10", "20", "30", sum(토탈) as 토탈 from ( select job 직업, sum(DECODE(DEPTNO, 10, SAL, 0)) AS "10", // 부서번호가 10이면 월급출력 sum(DECODE(DEPTNO, 20, SAL, 0)) AS "20", sum(DECODE(DEPTNO, 30, SAL, 0)) AS "30", sum(DECODE(DEPTNO, 10, SAL, 20, SAL, 30, SAL,0)) AS 토탈 from emp group by rollup(job) ) group by (직업, "10","20", "30") order by 직업 ;
- 해석
- 부서번호 10, 20, 30을 가로로 출력하고 싶어서 sum+decode를 사용
sum(DECODE(DEPTNO, 10, SAL, 20, SAL, 30, SAL,0)) AS 토탈
는 부서번호 10, 20, 30의 월급들만 더하고싶어서 작성- from절 서브쿼리는 2번 부분 코드의 별칭을 사용하고싶어 사용
- roll up 사용해서 직업별 토탈 월급을 출력했고, null값이 나오면
nvl(직업,'토탈')
로 써주어서 직업 맨 밑에 토탈이라고 출력되게 함.다른분들 답(roll up 사용)
select nvl(job, '토탈') as 직업, sum(decode(deptno, 10, sal)) as "10", sum(decode(deptno, 20, sal)) as "20", sum(decode(deptno, 30, sal)) as "30", sum(sal) as 토탈 from emp group by rollup(job);
다른분들 답(grouping sets 사용)
select NVL(job, '토탈') as 직업, sum(decode(deptno, 10, sal, null)) as "10", sum(decode(deptno, 20, sal, null)) as "20", sum(decode(deptno, 30, sal, null)) as "30", sum(sal) as 토탈 from emp group by grouping sets(job, ()) // job별로, 전체 () 별로 order by 직업;
- rollup은 정렬이 그냥 ABC 순으로 되네!는줄 알았는데 grouping sets도 정렬 알아서 됨