데이터 설계는? 설계에 대한 이해, 데이터의 관계에 대한 이해를 바탕으로 설계할 수 있다.
일양의 차이? 실행계획을 통해 쿼리문을 실행하는 일의 양, 필요한 비용을 확인할 수 있다. 전체 범위, 부분 범위 처리의 차이를 알고 설계해야하며, 이를 위해 쿼리문에 대해 학습하고 경험하는 것이 필요하다.
- 부서집합의 부서번호가 사원집합으로 가게 된 것은 관계 때문이며, 부서번호를 외래키라고 함.
- 1:n의 관계가 생기는 것을 릴레이션이라고 함.
[decode]
--decode sum과 함께 많이 쓰임(소계, 총계 등)
SELECT
sum(decode(JOB,'CLERK',sal,NULL)) AS "CLERK"
,sum(decode(JOB,'SALESMAN',sal,NULL)) AS "SALESMAN"
,sum(decode(JOB,'CLERK',NULL,'SALESMAN',NULL,sal)) AS "ETC"
FROM emp;
[rowid & rownum]
[그룹함수]
SELECT max(sal), min(sal), count(sal),sum(sal), avg(sal) FROM emp;
-- 5000 800 14 29025 2073.21428571429
해결방법 1 : 유효하지 않은 값 max를 붙여라 → 추천하지 않는다.
해결방법 2 : Group by절 사용(단, 효과가 전혀 없을 수 있다.)
--1번 해결방법. max는 단지 문법적 문제를 피하기 위함
--유효하지 않은 값이기 때문에 사용시 유의
SELECT max(sal), max(ename) FROM emp;
--2번 해결방법.
SELECT max(sal), ename
FROM emp
GROUP BY ename;
[case]
SELECT 등급,count(등급) AS "갯수"
FROM(SELECT
CASE
WHEN salary > 70000000 THEN 'A'
WHEN salary BETWEEN 50000001 AND 70000000 THEN 'B'
WHEN salary BETWEEN 30000001 AND 50000000 THEN 'C'
ELSE 'D'
END AS "등급"
FROM temp
)
GROUP BY 등급
ORDER BY 등급;
SELECT
count(CASE WHEN salary > 70000000 THEN 'A' END) AS "A"
,count(CASE WHEN salary BETWEEN 50000001 AND 70000000 THEN 'B' END) AS "B"
,count(CASE WHEN salary BETWEEN 30000001 AND 50000000 THEN 'C' END) AS "C"
,count(CASE WHEN salary<=30000000 THEN 'D' END) AS "D"
FROM temp;
[ERwin Tip]
[RDBMS]
[인덱스 (index)]
--둘의 실행계획 차이를 확인할 줄 알아야 한다.
SELECT empno FROM emp;
--empno의 경우, PK키이며 인덱스 값을 가진다.
--오름차순으로 정렬되어 조회된다.
SELECT empno, ename FROM emp;
[실행계획]
[💡힌트문]
-- /*+ ORDERED */: From절 나열된 테이블 순서대로 접근
-- /*+ LEADING */ : 원하는 순서로 테이블 접근 경로를 설정
-- /*+ USE_NL(B) */ : 인자값(B)으로 접근할 때 Nested Loop Join을 사용
-- /*+ USE_HASH(B) */ : 인자값(B)으로 접근할 때 Hash Join을 사용
-- /*+ INDEX(B) */ : 테이블의 인덱스 중 어떤 인덱스를 사용할지 지정
-- /*+ FULL(테이블명) PARALLEL(테이블명 병렬숫자) */ : Full은 테이블 전체를 풀스캔, Parallel은 병렬처리를 위한 힌트절
--rule base 비용에 따른 실행계획 설정(Nested Loop사용)-> 8밀리초
SELECT /*+ rule */ *
FROM emp, dept
WHERE emp.deptno = dept.deptno;
--구문입력한대로 Hash Join 사용 -> 13밀리초
SELECT *
FROM emp, dept
WHERE emp.deptno = dept.deptno;
[Join]
--조건을 넣어 해당하는 값만 조회 가능
SELECT empno, ename, dept.dname
FROM emp, dept
WHERE emp.deptno = dept.deptno;
Plan
SELECT STATEMENT ALL_ROWSCost: 7 Bytes: 770 Cardinality: 14
3 HASH JOIN Cost: 7 Bytes: 770 Cardinality: 14
1 TABLE ACCESS FULL TABLE SCOTT.DEPT Cost: 3 Bytes: 88 Cardinality: 4
2 TABLE ACCESS FULL TABLE SCOTT.EMP Cost: 3 Bytes: 462 Cardinality: 14
[퀴즈]
--날짜별 판매개수, 판매가격
--맨 아래 로우에 '총계'추가
SELECT decode(A.rno,1,indate_vc,2,'총계') AS "판매날짜"
,to_char(sum(qty_nu)||'개') AS "판매개수"
,to_char(sum(qty_nu*price_nu)||' 원')AS "판매가격"
FROM t_orderbasket,
(
SELECT 1 rno FROM dual
UNION ALL
SELECT 2 FROM dual
)A
GROUP BY decode(A.rno,1,indate_vc,2,'총계')
ORDER BY decode(A.rno,1,indate_vc,2,'총계');
SELECT dept
,decode(rno,1,'1학년',2,'2학년',3,'3학년',4,'4학년') AS "학년"
,decode(rno,1,fre,2,sup,3,jun,4,sen) AS "정원"
FROM test11,
(
SELECT ROWNUM rno FROM dept WHERE ROWNUM <=4
)
ORDER BY dept ASC, decode(rno,1,'1학년',2,'2학년',3,'3학년',4,'4학년') ASC;
SELECT
decode(b.rno,1,dname,2,'총계') AS "dname",sum(clerk) AS "CLERK" , sum(salesman) AS "SALESMAN", sum(etc) AS "ETC"
FROM
(
SELECT dname, clerk, salesman, etc, dept_sal
FROM
(
SELECT
deptno, CLERK, SALESMAN, ETC, DEPT_SAL
FROM
(
SELECT deptno,
sum(DECODE (JOB, 'CLERK', sal)) AS "CLERK",
sum(DECODE (JOB, 'SALESMAN', sal)) AS "SALESMAN",
sum(DECODE (JOB, 'CLERK', NULL, 'SALESMAN', NULL, sal)) AS "ETC",
sum(sal) AS "DEPT_SAL"
FROM emp
GROUP BY deptno
)
)E, dept d
WHERE E.deptno = d.deptno
)A,
(SELECT ROWNUM rno FROM dept WHERE ROWNUM < 3)b
GROUP BY decode(b.rno,1,dname,2,'총계')
ORDER BY decode(b.rno,1,dname,2,'총계');
🤔문제 제기
⇒ 인라인뷰를 고민해보자!!
⇒ 더미테이블 사용하기(총계가 출력될 수 있도록)
❓왜 중첩 쿼리 사용?