[ORACLE] 표준 조인

Posted by 신희준 on June 21, 2018


2018 - 06 - 21 (목)


오라클 표준조인

  • INNER JOIN

INNER JOIN은 OUTER JOIN 과 대비하여 내부 JOIN 이라고 하며 JOIN 조건에서 동일한 값이 있는 행만 반환한다.

SELECT EMP.DEPTNO, EMPNO, ENAME, DNAME
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO;

--아래 INNER JOIN 한 결과가 위와 같은 결과가 나온다.

SELECT EMP.DEPTNO, EMPNO, ENAME, DNAME
FROM EMP INNER JOIN DEPT
ON EMP.DEPTNO = DEPT.DEPTNO;
  • NATURAL JOIN

NATURAL JOIN은 두 테이블 간의 동일한 이름을 갖는 모든 컬럼들에 대해 EQ JOIN을 수행한다.


SELECT DEPTNO, EMPNO, ENAME, DNAME
    FROM EMP NATURAL JOIN DEPT;

-- 위와 같은 쿼리는 신기하게도 두개 테이블에서 공통적으로 있는 DEPTNO을 자동 인식하여 JOIN 한다. 

EMP.DEPTNO, EMPNO, ENAME, DNAME
    FROM EMP NATURAL JOIN DEPT;

--NATURAL JOIN에 사용된 열은 식별자를 가질 수 없음. 즉 위의 쿼리는 오류이다.

SELECT * 
    FROM EMP NATURAL JOIN DEPT;
-- 공통된 컬럼이 DEPTNO 이므로 DEPTNO 가 첫번째 칼럼이 된다.

-- 별개로 이너조인과 비교하자면 
SELECT * 
FROM EMP INNER JOIN DEPT
ON EMP.DEPTNO = DEPT.DEPTNO;

--위의 쿼리를 실행하면 상위 쿼리와달리 DEPT_NO 를 공통으로 인식하지 않고 별개의 컬럼으로 인식하여 출력한다.

--

  • USING 조건절

USING 조건절


SELECT *
FROM DEPT JOIN DEPT_TEMP
USING (DEPTNO);
--아래와 같은 값을 갖는다.

Post Sample Image

SELECT * 
FROM DEPT JOIN DEPT_TEMP
USING (DNAME);
--아래와 같은값을 갖는다.

Post Sample Image

  • ON 조건절

ON 조건절은 WHERE 절의 JOIN 조건과 같은 기능을 하면서도 명시적으로 JOIN의 조건을 구분할 수 있다. 또한 ALIAS 를 사용가능하다.


SELECT E.EMPNO, E.ENAME, E.DEPTNO, D.DNAME
FROM EMP E JOIN DEPT D
ON (E.DEPTNO = D.DEPTNO);

OUTER JOIN

JOIN 조건에서 동일한 값이 없는행도 반환 할 때 사용할 수 있다.

  • LEFT OUTER JOIN : 조인 수행시 먼저 표기된 좌측 테이블에 해당하는 데이터를 먼저 읽은 후 , 나중 ㅍ기된 우측 테이블에서 JOIN 대상 데이터를 읽어온다.

  • RIGHT OUTER JOIN : 위의 반대이다.

  • FULL OUTER JOIN : FULL OUTER JOIN 은 양쪽 모두 출력하는 것이다.

Post Sample Image

해당 출력 결과는 EMP 테이블을 SELECT한것으로 DEPTNO는 10~30 까지 존재한다.

Post Sample Image

하지만 위 이미지는 아우터조인을 한것으로 DEPT 테이블에는 DEPTNO 가 40까지 존재하기 때문에 우측에 있는 DEPT 테이블을 먼저 읽고 좌측에 EMP테이블을 붙인다. 만약 DEPTNO 에 해당하는 값이 없을경우 NULL 을 기입한다.


SELECT E.ENAME, D.DEPTNO, D.DNAME, D.LOC
FROM EMP E RIGHT OUTER JOIN DEPT D
ON E.DEPTNO = D.DEPTNO;

집합 연산자

여러개의 질의의 결과를 연결하여 하나로 결합하는 방식

  • UNION : 여러개의 SQL 문의 결과에 대한 합집합으로 결과에서 모든 중복된 행은 하나의 행으로 만든다.

  • UNION ALL : 중복된 행도 그대로 결과로 표시한다

  • INTERSECT : 여러개의 SQL 결과물에대한 교집합이다.

  • EXCEPT : 여러개의 SQL 결과물에대한 차집합이다. 중복된 행은 하나의 행으로 만든다.

계층형 질의

테이블에 계층형 데이터가 존재하는 경우 데이터를 조회하기 위해서 계층형 질의를 사용한다.

SELECT ...
FROM 테이블 명
WHERE CONDITION AND CONDITION...
START WITH CONDITION
CONNECT BY [NOCYCLE] CONDITION AND CONDITION ...
[ORDER SIBLINGS BY COLUMN, COLUMN, ...]


SELECT CONNECT_BY_ROOT 사원 루트사원, SYS_CONNECT_BY_PATH(사원, '/') 경로, 사원, 관리자
FROM 사원
START WITH 관리자 IS NULL
CONNECT BY PRIOR 사원 = 관리자;

--위와 같은 형태로 사용한다
  • START WITH 절은 계층 구조 전개의 시작 위치를 지정하는 구문으로 루트 데이터를 지정한다.
  • CONNECT BY 절은 다음에 전개될 자식 데이터를 지정하는 구문이다.
  • PRIOR : CONNECT BY 절에서 사용되며, 현재 읽은 칼럼을 지정한다.
  • NOCYCLE : 데이터를 전개하면서 이미 나타났던 동일한 데이터가 전개 중에 다시 나타난다면 이것을 가리켜 사이클이 형성되었다고 말한다.

CONNECT_BY_ROOT (루트노드 찾기)

CONNECT_BY_ROOT 컬럼

  • 단독으로 사용되지 못하고 일반컬럼과 같이 사용해야함.

CONNECT_BY_ISCYCLE (중복 참조값 찾기)

CONNECT_BY_ISCYCLE은 반드시 CONNECT BY절에 NOCYCLE이 명시되어 있어야 사용이 가능하다.

CONNECT_BY_ISLEAF (리프노드 찾기)

계층형 쿼리에서 해당 로우가 리프노드인지(지삭노드가 없는 노드인지) 여부를 체크하여, 리프노드에 해당할경우 1을 그렇지 않을 경우 0을 반환

SYS_CONNECT_BY_PATH (루트 찾아가기)

SYS_CONNECT_BY_PATH ( column, char )

서브 쿼리

SELECT column1, column2 , column3
FROM TABLE
WHERE column1 = (SELECT column1
                 FROM TABLE
                 WHERE column1 = 'xxx')
ORDER BY column1;

그룹 함수

  • ROLLUP 함수

부분합 느낌으로 출력한다.

아래는 일반적인 GROUP BY 문이다.

SELECT DNAME, JOB,
       COUNT(*) "Total Empl",
       SUM(SAL) "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY DNAME, JOB
ORDER BY DNAME, JOB;

Post Sample Image

아래는 ROLLUP 을 통한 그루핑이다.

SELECT DNAME, JOB,
       COUNT(*) "Total Empl",
       SUM(SAL) "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY ROLLUP  (DNAME, JOB);

Post Sample Image

  • CUBE 함수

ROLLUP 에서는 단순히 SubTotal 만을 생성하였지만 , CUBE 는 결합 가능한 모든 값에 대하여 다차원 집계를 생성한다.


SELECT 
 CASE GROUPING(DNAME) WHEN 1 THEN 'ALL Departments' ELSE DNAME END AS DNAME,
 CASE GROUPING(JOB)   WHEN 1 THEN 'All Jobs'        ELSE JOB   END AS JOB,
 COUNT(*)   "Total Empl",
 SUM(SAL)   "Total Sal"
 FROM EMP, DEPT
 WHERE DEPT.DEPTNO = EMP.DEPTNO
 GROUP BY CUBE (DNAME, JOB);

Post Sample Image

윈도우 함수

  • RANK 함수

일반적인 RANK 함수는 만약 1등이 2명인 경우 2등이 없어진다. 이러한 상황에서 2등을 주고싶을 때는 DENSE_RANK 를 사용한다.

SELECT JOB, ENAME, SAL,
    RANK() OVER(ORDER BY SAL DESC) ALL_RANK,
    RANK() OVER(PARTITION BY JOB ORDER BY SAL DESC) JOB_RANK
FROM EMP;

--DENSE_RANK 와 RANK 비교

SELECT JOB, ENAME, SAL,
       RANK()       OVER (ORDER BY SAL DESC) RANK,
       DENSE_RANK() OVER (ORDER BY SAL DESC) DENSE_RANK
FROM EMP;
  • SUM 함수

SUM 함수를 이용하여 파티션별 윈도우의 합을 구할 수 있다.

ex) 사원들의 급여와 같은 매니저를 두고 있는 사원들의 SALARY 합을 구한다.

SELECT MGR, ENAME, SAL, SUM(SAL) OVER (PARTITION BY MGR) MGR_SUM
FROM EMP;

아래와 같이 출력된다. ( partition by 컬럼명 으로 해당 컬럼을 기준으로 sum을 한다.)

Post Sample Image

  • MAX , MIN ,AVG (최대, 최소, 평균)

select mgr, ename, sal
from   (select mgr, ename, sal, max(sal) over (partition by mgr) as iv_max_sal from emp)
       where sal = iv_max_sal;

위 쿼리는 MGR 컬럼을 기준으로 SALARY 가 가장 높은 값을 가진 열만 반환한다.


SELECT DEPTNO, ENAME, SAL,
       FIRST_VALUE(ENAME) OVER (PARTITION BY DEPTNO ORDER BY SAL DESC
       ROWS UNBOUNDED PRECEDING) AS DEPT_RICH
FROM   EMP;

  • COUNT
SELECT ENAME, SAL,
       COUNT(*) OVER (ORDER BY SAL
       RANGE BETWEEN 50 PRECEDING AND 150 FOLLOWING) AS SIM_CNT
FROM EMP;

Post Sample Image