배웠던 핵심 내용을 떠올리기 위한 기록으로 글을 작성합니다.
FK
는 다른 테이블의 PK를 가져오는 것이다.
관계를 형성할 때 사용한다.
각 테이블에서의 컬럼 이름이 달라도 상관이 없다.
FK는 중복이 될 수 있다. ( 1:N 관계
)
참조 무결성 제약조건
**BLANK**
, **BLANK**
는 ASCII 코드 값이 부여되어 있음 )SELECT SAL * 12 as ANNUAL_SALARY
FROM emp
ORDER BY ANNUAL_SALARY asc;
WHERE 절에서 LIKE를 가능한 쓰지 말자! ( = 19g 부터는 ‘A%’ 라면, A까지는 인덱스를 탄다, 하지만 그 이후에 자료들은 인덱스를 타지 않는다. Full-Scan )
-- ( 카티션 곱 ) : Cartesian Product / 합성곱, 모든 경우의 수
select e.ename, d.deptno
from emp e, dept d;
-- Cartesian Product + WHERE 절로 조건 ( = JOIN )
select e.ename, d.deptno
from emp e, dept d
where e.deptno = d.deptno;
Oracle 전용 SQL
SELECT e.ename, d.deptno
FROM emp e, dept d
where e.deptno(+) = d.deptno;
SELECT d.deptno, e.ename
FROM emp e, dept d
where d.deptno = e.deptno(+);
-- Outer Join (+) 연산자. 부족한 쪽에 (+) 로 채워줌.
-- 주의주의 :: e.deptno --> null 출력, d.deptno (정답)
SELECT e.ename, e.deptno, d.deptno
FROM emp e, dept d
where e.deptno(+) = d.deptno;
ANSI 표준 SQL
-- ANSI 표준 SQL OUTER JOIN
-- LEFT/RIGHT OUTER JOIN
SELECT
e.ename,
d.deptno
FROM dept d
LEFT OUTER JOIN emp e ON d.deptno = e.deptno;
-- SELF JOIN
SELECT
e.empno as EMPLOYEE_NO,
e.ename as EMPLOYEE_NAME,
m.empno as MANAGER_NO,
m.ename as MANAGER_NAME
FROM
EMP e,
EMP m
WHERE
e.mgr = m.empno;
-- 매니저가 없는 경우도 출력하기 ( 없는 경우 )
SELECT
e.empno as EMPLOYEE_NO,
e.ename as EMPLOYEE_NAME,
COALESCE(m.empno, -1) as MANAGER_NO,
COALESCE(m.ename, 'NOT EXIST') as MANAGER_NAME
FROM
EMP e
LEFT OUTER JOIN
EMP m
ON
e.mgr = m.empno;
-- JOIN WITH MORE THAN 2 TABLES
SELECT
c.name as cname,
c.custid as cid,
o.ordid as oid,
i.itemid as iid
FROM
CUSTOMER c
INNER JOIN
ORD o
ON
c.custid = o.custid
INNER JOIN
ITEM i
ON
c.ordId = i.ordid;
-- FROM 에 3개 테이블
SELECT
c.name as cname,
c.custid as cid,
o.ordid as oid,
i.itemid as iid
FROM
CUSTOMER c, ORD o, ITEM i
WHERE
c.custid = o.custid
AND
o.ordid = i.ordid;
-- Non-Equi Join ( where 절에 < , >, <=, >= 를 활용한 JOIN )
-- Cartesian Product 이후, WHERE 절로 자르기
SELECT
e.empno as empno,
e.ename as ename,
e.sal as salary,
sg.grade as grade,
sg.losal as lowsal,
sg.hisal as hisal
FROM
EMP e, SALGRADE sg
WHERE
e.sal >= sg.losal
AND
e.sal <= sg.hisal;
-- AVG, MAX, MIN, SUM
-- 10번 부서 사람들의 평균, 최대, 최소, 총합 급여
SELECT
ROUND(AVG(SAL),1) as avgSal,
MAX(SAL) as maxSal,
MIN(SAL) as minSal,
SUM(SAL) as sumSal
FROM
EMP
WHERE
DEPTNO = 10;
-- GROUP BY DEPTNO
SELECT
DEPTNO,
ROUND(AVG(SAL),1) as avgSal,
MAX(SAL) as maxSal,
MIN(SAL) as minSal,
SUM(SAL) as sumSal
FROM
EMP
GROUP BY
DEPTNO
ORDER BY
DEPTNO ASC;
SELECT SUM(SAL) as s_sal
FROM EMP;
SELECT
deptno,
SUM(sal) as s_sal
FROM
emp
GROUP BY
deptno
ORDER BY
s_sal DESC;
보통 UNIQUE하게 뽑는 방법은 일반적으로 이렇게 나눌 수 있다.
( DISTINCT도 여러 컬럼에 대한 유니크한 튜플을 뽑을 수 있다.
일반적으로 GROUP BY를 사용하는 것 )
SELECT
DISTINCT deptno
FROM
emp;
-- DISTINCT 와 같은 문법
SELECT
deptno
FROM
emp
GROUP BY
deptno;
-- ORA-00937 : Not a single-group group function
-- SELECT에서 사용한 일반 컬럼을 GROUP BY에 넣지 않으면 937에러가 난다.
SELECT
DEPTNO,
ROUND(AVG(SAL),1) as avgSal,
MAX(SAL) as maxSal,
MIN(SAL) as minSal,
SUM(SAL) as sumSal
FROM
EMP
--GROUP BY
-- DEPTNO
ORDER BY
DEPTNO ASC;
-- 평균 급여가 2000 이상인 부서만 출력 (★)
-- ORA-00934 : GROUP FUNCTION is not allowed here.
-- 2. 그룹 함수는 WHERE자리에 오지 못한다.
-- 그룹에 대한 조건은 HAVING 으로 적용한다!
SELECT
DEPTNO,
AVG(SAL)
FROM
EMP e
GROUP BY
DEPTNO
HAVING
AVG(SAL) >= 2000;
-- HAVING에 그룹함수가 아닌 조건을 넣어도 될까? -> OK
SELECT
~~
FROM
MEM
GROUP BY
지역
HAVING
지역 IN ('서울', '경기')
NULL을 없는 취급
해서 센다.NULL을 취급
하지 않는다.SELECT
COUNT(COMM),
COUNT(1),
COUNT(*)
FROM
EMP;
SELECT
ROWID,
ROWNUM,
EMPNO,
ENAME
FROM
EMP;
-- NULL인 컬럼이 있는지 없는지 확인할 수 있는 쿼리
SELECT
COUNT(COMM),
COUNT(1)
FROM
EMP;
-- 이것도 가능
SELECT
*
FROM
EMP
WHERE
COMM IS NULL;
-- AVG -> 그룹함수로, NULL값을 무시함.
SELECT
COMM,
AVG(COMM)
FROM
EMP;
-- NVL을 통해 NULL을 0으로 대체 후 AVG 계산
SELECT
AVG(NVL(COMM,0))
FROM
EMP;
-- 2. 그룹에 대한 조건을 준다. ( HAVING -> GROUP BY에 대한 조건을 주는 것 )
SELECT
JOB,
AVG(SAL) as avgsal
FROM
EMP
GROUP BY
JOB
HAVING
JOB IN ('CLERK', 'SALESMAN');
-- 3. 2와 결과는 동일, 근데 더 효율적 ( 트래픽을 덜 잡아먹는다 )
SELECT
JOB,
AVG(SAL) as avgsal
FROM
EMP
WHERE
JOB IN ('CLERK', 'SALESMAN')
GROUP BY
JOB;
-- 각 부서별 평균급여 중 최대평균급여 출력
SELECT
MAX(AVG(SAL))
FROM
EMP
GROUP BY
DEPTNO;
-- 각 부서별 평균급여 중 최대평균급여 출력
-- 에러 937 에러
SELECT
DEPTNO,
MAX(AVG(SAL))
FROM
EMP
GROUP BY
DEPTNO;
-- 각 부서별 평균 급여 중, 최대 평균 급여인 부서
SELECT
DEPTNO
FROM
EMP
GROUP BY
DEPTNO
HAVING
AVG(SAL) = (
SELECT
MAX(AVG(SAL))
FROM
EMP
GROUP BY
DEPTNO
);
937 에러
는 각 행이 다른 테이블을 한번에 보여주려할 때 나타나는 에러이다.-- 1. DALLAS에서 근무하는 사원의 이름, 직업, 부서번호, 부서이름을 출력.
SELECT
e.ename,
e.job,
e.deptno,
d.dname
FROM
EMP e
JOIN
DEPT d
ON
e.deptno = d.deptno
WHERE
d.loc = 'DALLAS';
-- 2. 직업이 'SALESMAN'인 사원들의 직업과 그 사원이름, 부서 이름을 출력하라.
SELECT
e.JOB,
e.ENAME,
d.DNAME
FROM
EMP e
JOIN
DEPT d
ON
e.deptno = d.deptno
WHERE
e.JOB = 'SALESMAN';
-- 부서번호가 10, 20번인 사원들의
-- 부서번호, 부서이름, 사원이름, 급여를 출력
-- 부서번호가 낮은 순, 급여가 높은 순으로 출력
SELECT
d.deptno,
d.dname,
e.ename,
e.sal
FROM
DEPT d
JOIN
EMP e
ON
d.deptno = e.deptno
WHERE
d.deptno in (10,20)
ORDER BY
d.deptno ASC, e.sal DESC;
-- EMP 테이블의 모든 사원번호, 사원명, 매니저번호, 매니저명을 출력하라.
SELECT
e.empno,
e.ename,
e.mgr as mgr_no,
m.ename as mgr_name
FROM
EMP e
JOIN
EMP m
ON
e.mgr = m.empno;
-- EMP 테이블에서 부서 인원이 4명보다 많은 부서의 부서번호, 인원수, 급여의 합을 출력하시오.
SELECT
deptno,
count(empno) as pcount,
sum(sal) as whole_sal
FROM
EMP
GROUP BY
deptno
HAVING
count(empno) > 4;