ORACLE_04_이론정리_JOIN, 서브쿼리
참고 ] having 절 : 그룹화한 결과를 필터링 할때 필터링 조건을 기술하는 절..
where 절에는 그룹함수를 사용하지 못하지만, having 절에는 그룹함수를 사용할 수 있다.
JOIN : Relation Database Management System (=RDMBS) 에서는 데이터의 중복(=무결성)을
피하기 위해서 테이블을 분리하고 그럼으로서 테이블들 간 관계가 형성이 되었다.
그런데 분리된 테이블에서 데이터를 추출해낼때 사용하는 문법이 JOIN 이다.
참고 ] 오라클역시 er형태의 데이터베이스이다.
ER : 엔티티(테이블)끼리의 관계를 이야기 하고 이런 관계들로 테이블을 관리하는 데이터베이스를 관계형
데이터베이스라고 한다.
참고 ] 관계형데이터베이스에서는 여러개의 테이블에서 동시에 검색하는 기능은 이미 가지고 있다.
이때 여러개의 테이블에서 데이터 동시에 검색하면 Cartesion Product가 만들어지는데
이 결과에는 정확하지 않은 데이터도 포함되어 있다.
따라서 정확한 데이터만 필터링해서 꺼내와야 하는데 이때 이 필터링 하는 작업이 JOIN이라고 한다.
종류 ] Inner Join : 나열된 테이블들의 결과 집합 안에서 꺼내오는 조인
- Equi Join : 조인을 할때 동둥비교연산자로 조인을 하는 경우
- Non Equi Join : 조인을 할때 동등비교연산자 이외의 연산자로 조인하는 경우
Outer Join : Catesian Product에 포함되지 않는 데이터를 가져오는 조인
형식 : 테이블이름, 필드이름 = 테이블이름.필드이름(+) 이때 (+)는 NULL로 표현되어야 할 테이블쪽에 붙여준다.
Self Join : 조인을 하는데 대상테이블이 같은 테이블을 사용하는 조인
-- 영문색상이름 테이블
DROP TABLE ecolor;
CREATE TABLE ecolor (
ceno NUMBER(3) -- 영문 칼라 일련번호
CONSTRAINT ECLR_NO_PK PRIMARY KEY,
code VARCHAR2(7) -- 칼라 코드값
CONSTRAINT ECLR_CODE_UK UNIQUE
CONSTRAINT ECLR_CODE_NN NOT NULL,
name varchar2(20)
CONSTRAINT ECLR_NAME_NN NOT NULL
);
-- 데이터추가
INSERT INTO
ecolor
VALUES(
100, '#FF0000', 'red'
);
INSERT INTO
ecolor
VALUES(
101, '#00FF00', 'green'
);
INSERT INTO
ecolor
VALUES(
102, '#0000FF', 'blue'
);
INSERT INTO
ecolor
VALUES(
103, '#000000', 'purple'
);
commit;
-- 영문칼라테이블 조회
SELECT * FROM ecolor;
COMMIT; -- 메모리의 작업영역에서 작업한 내용을 데이터베이스에 적용시키는 명령
CREATE TABLE kcolor (
ckno NUMBER(3)
CONSTRAINT KCLR_NO_PK PRIMARY KEY,
code VARCHAR2(7)
CONSTRAINT KCLR_CODE_UK UNIQUE
CONSTRAINT KCLR_CODE_NN NOT NULL,
name varchar2(20)
CONSTRAINT KCLR_NAME_NN NOT NULL
);
-- 데이터추가
INSERT INTO
kcolor
VALUES(
100, '#FF0000', '빨강'
);
INSERT INTO
kcolor
VALUES(
101, '#00FF00', '녹색'
);
INSERT INTO
kcolor
VALUES(
102, '#0000FF', '파랑'
);
commit;
SELECT * FROM ecolor;
SELECT * FROM kcolor;
SELECT
*
FROM
ecolor, kcolor
;
SELECT
*
FROM
emp e, emp ee
;
SELECT
ceno cno, e.code, e.name ename, k.name kname
FROM
ecolor e, kcolor k
WHERE
e.code = k.code -- 조인조건
;
ANSI JOIN : 질의명령은 데이터베이스(DBMS)에 따라서 약간씩 그 문법이 달라진다.
ANSI 형식이란 미국국립표준협회(ANSI)에서 공통의 질의명령을 만들고자 해서 통일된 방식의 명령을 만들어놓은 것.
따라서 DBMS 를 가리지 않고 실행이 된다.
1. Cross Join : 오라클의 Cartesion Product 를 생성하는 조인
형식 ] SELECT 필드이름,..... FROM 테이블 CROSS JOIN 테이블2;
2. Inner Join : Equi Join, Non Eqi Join, Self Join
형식 ] SELECT 필드이름,....
FROM 테이블1 (INNER) JOIN 테이블2....
ON 조인조건
WHERE 일반조건
참고 ] 조인조건은 ON 절에서 기술하고 일반조건은 WHERE절에서 기술한다.
INNER JOIN이 가장 일반적인 조인이기 문에 INNER 라는 단어를 생략하면 INNER JOIN을
해석해서 실행하게 된다.
3. OUTER JOIN : Cartesion
형식 ] SELECT 필드이름...
FROM 테이블1 LEFT || RIGHT || FULL OUTER JOIN 테이블2 참고) || : 또는
ON 조인조건...;
이때 방향은 데이터가 있는 쪽 테이블을 가리키면 된다.
참고 ] 조인이 2개이상 되는 경우에는
형식 ] SELECT
FROM 테이블이름
JOIN 테이블2
ON 조인조건
JOIN 테이블3
ON 조인조건2;
CROSS JOIN : 사원 정보와 부서정보를 크로스조인하세요.
SELECT
*
FROM EMP CROSS JOIN DEPT;
INNER JOIN : 사원들의 사원직급, 부서번호, 부서이름을 조회하세요
SELECT EMAME 사원이름, JOB 직급, E.DEPTNO 부서번호, DNAME 부서이름
FROM EMP E INNER JOIN DEPT D
ON --조인조건절
E.DEPTNO = D.DEPTNO
;
--81년 입사한 사원들의 사원이름, 직급, 입사년도, 부서이름을 조회하세요
SELECT ENAME 사원이름, JOB 직급, TO_CHAR(HIREDATE,'YY') 입사년도,DNAME 부서이름
FROM EMP E INNER JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
WHERE TO_CHAR(HIREDATE,'YY')= '81'
;
--사원들의 사원이름, 급여, 급여등급을 조회하세요. NON EQUI JOIIN
SELECT ENAME, SAL, GRADE
FROM EMP JOIN SALGRADE
ON SAL BETWEEN LOSAL AND HISAL;
예 ] 사원들의 사원이름, 상사이름을 조회하세요
-- INNERJOIN VER.
SELECT E.ENAME 사원이름, NVL(S.ENAME,'상사없음') 상사이름
FROM
EMP E JOIN EMP S
ON
E.MGR = S.EMPNO(+);
-- OUTERJOIN VER.
SELECT
E.ENAME 사원이름, S.ENAME 상사이름
FROM
EMP E LEFT OUTER JOIN EMP S
ON
E.MGR = S.EMPNO;
예 ] 사원들의 사원이름, 부서이름, 급여, 급여등급을 조회하세요
SELECT ENAME 사원이름, DNAME 부서이름,SAL 급여,GRADE 급여등급
FROM EMP E -- 공통적으로 조인하는 기본테이블을 넣어줘야함
JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
JOIN SALGRADE
ON E.SAL BETWEEN LOSAL AND HISAL;
NATURAL JOIN : 자동조인 반드시 조인 조건식에 사용하는 필드의 이름이 동일하고
반드시 동일한 필드가 한개일때 사용할 수 있는 조인
자동으로 중복되는 필드를 사용해서 조인하기 문에 조인조건을 기술하지 않는다.
형식 ] SELECT 필드이름....
FROM 테이블 1
NATURAL JOIN 테이블2;
USING JOIN : 반드시 조인 조건식에 사용하는 필드의 이름이 동일한 경우
그리고 같은 이름을 필드가 여러개 존재해도 무방하다.
형식 ] SELECT 필드이름..
FROM 테이블1
JOIN 테이블2
USING (조인에 사용할 필드이름)
예 ] 사원들의 사원이름, 부서이름을 조회하세요
SELECT ENAME 사원이름, DNAME 부서이름
FROM EMP
NATURAL JOIN DEPT; --필드를 꺼내서 똑같은 이름의 필드를 꺼내서 JOIN함
예 ] TMP 테이블과 부서정보 테이블을 이용해서 사원들의 사원이름, 부서위치를 조회하세요
--TMP 테이블 생성
CREATE TABLE TMP
AS
SELECT
E.*, DNAME
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO;
--TMP 테이블 조회
SELECT ENAME 사원이름, LOC 부서위치
FROM TMP
JOIN DEPT
USING (DEPTNO);
부질의(SUB QUERY, 서브질의) : 질의명령 안에 다시 질의명령을 포함하는 경우
포함된 그 질의명령을 서브질의 또는 서브쿼리 라고 부른다.
예 ] 이름이 SMITH인 사원과 같은 부서에 있는 사원들의 정보를 조회하세요
==> 이 경우 SMITH의 부서번호를 알아내기 위해서 먼저 질의명령이 실행되어야 한다.
SMITH 사원의 부서를 뽑고 (부서가 같다면) 각 사원들의 부서번호 비교.........
==> 부서번호를 이용해서 정보를 조회
이때 위의 질의명령을 아래 메인 질의명령에서 사용해서 명령을 보내고 조회해서 사용해야 한다.
이때 서브질의를 감싸는 질의명령을 메인질의 명령이라고 한다.
서브질의의 위치에 따른 결과
1. SELECT 절 : 이 부분에 사용되는 질의명령은 결과가 반드시 한행 , 한 필드가 나와야 한다.
2. FROM 절 : FROM 절에는 테이블이 나열되어야 한다. 그런데 조회질의 명령의 결과는 마치 테이블과 같다.
그러면 이 조회 질의 명령의 결과를 테이블처럼 사용할 수 있는 방법
FROM 절 안에 들어가는 서브질의를 특별히 마치 테이블과 같다 해서 INLINE TABLE이라고
부른다.
사용은 질의명령을 보낼때 사용한 별칭을 사용해서 데이터를 꺼내야 한다.
3. WHERE 절
1. 단일행 단일필드로 결과가 발생하는 경우 : 결과를 비교에 사용하면 된다.
2. 다중행 단일필드로 결과가 발생하는 경우
-서브질의의 결과가 다중행으로 단일필드로 발생하는 경우 이 사용하는 연산자가
IN : 여러개의 데이터 중 하나만 맞으면 되는 경우. 여러값 중 하나와 묵시적으로 동등비교 처리한다.
ANY : 여러개의 데이터 중 하나만 맞으면 되는 경우 . 대소비교 연산자도 사용 가능
ALL : 여러개의 데이터가 모두 맞으면 되는 경우
==> 동등비교는 사용할 수 없고, 대소비교할 사용한다.
3. 다중필드 복수의 필드로 결과가 발생하는 방법
EXISTS : 여러개의 데이터 중 하나만 맞으면 되는 경우,
예 ] 이름이 SMITH인 사원과 같은 부서에 있는 사원들의 정보를 조회하세요
SELECT *
FROM EMP
WHERE DEPTNO = (
SELECT DEPTNO
FROM EMP
WHERE
ENAME = 'SMITH'
);
예 ] 사원들의 사원이름, 부서번호, 부서이름, 부서위치 조회
SELECT ENAME 사원이름, DEPTNO 부서번호,(
SELECT DNAME
FROM DEPT
WHERE E.DEPTNO = DEPTNO
) 부서이름,
(
SELECT LOC
FROM DEPT
WHERE E.DEPTNO = DEPTNO
) 부서위치
FROM EMP E;
IN : 직급이 MANAGER인 사원과 같은 부서에 속한 사원들의 사원이름, 직급 , 부서번호를 조회하세요
SELECT
ENAME 사원이름, JOB 직급, DEPTNO 부서번호
FROM EMP
WHERE DEPTNO= IN(
SELECT
DEPTNO
FROM
EMP
WHERE
JOB = 'MANAGER'
);
ANY : 각 부서 평균 급여보다 한 부서라도 급여가 높은 사람들의 사원이름, 사원급여, 부서번호를 조회하세요
SELECT
ENAME 사원이름, SAL 사원급여, DEPTNO 부서번호
FROM EMP
WHERE SAL> ANY( --한 부서라도....
SELECT AVG(SAL)
FROM EMP
GROUP BY DEPTNO
);
Outer Join
SELECT
ceno cno, e.code, e.name ename, k.name kname
FROM
ecolor e, kcolor k
WHERE
e.code = k.code(+) -- 조인조건
;
self join
예 ] 사원들의 사원이름, 상사번호, 상사이름, 상사급여 를 조회하세요
SELECT
e.ename 사원이름, e.mgr 상사번호, s.ename 상사이름, s.sal 상사급여
FROM emp e, emp s
WHERE
e.mgr = s.empno(+) --(+)Outer Join : king에 상사가 없으니까
--null값을 추가하기 위하여 null값이 있는 테이블에 (+)를 추가
;
예 ] 사원들의 사원이름, 직급, 급여, 급여등급을 조회하세요
SELECT
ENAME 사원이름, JOB 직급, SAL 급여, GRADE 급여등급
FROM EMP, SALGRADE
WHERE
SAL BETWEEN LOSAL AND HISAL
;
--사원들의 사원번호, 사원이름,직급, 부서이름, 부서위치를 조회하세요
SELECT EMPNO 사원번호, ENAME 사원이름, JOB 직급, DNAME 부서이름,LOC 부서위치
FROM EMP E, DEPT D --DEPT가 겹쳐서 구분해주기 위함
WHERE
E.DEPTNO = D.DEPTNO
;
예 ] 81년 입사한 사원의 사원이름, 직급, 입사일, 부서이름을 조회하세요
SELECT ENAME 사원이름, JOB 직급, TO_CHAR(HIREDATE,'YYYY"년 "MM"월" DD"일"') 입사, DNAME 부서이름
FROM EMP E, DEPT D
WHERE
E.DEPTNO = D.DEPTNO --조인조건
AND TO_CHAR(HIREDATE,'YY')='81'; --일반조건