Table of Contents

Relational Algebra

Dr. E.F.Codd의 RDBMS 논문(1970)을 기초로 한다.

연산자 SQL 설명
UNION UNION
UNION ALL
합집합 (중복 제거)
합집합 (중복 허용)
INTERSECTION INTERSECT 교집합 (공통 요소 추출)
DIFFERENCE EXCEPT
(Oracle : MINUS)
차집합 (앞SQL기준으로 - 뒤SQL)
PRODUCT CROSS JOIN 곱집합 (JOIN 조건이 없는 경우 생길 수 있는 모든 데이터의 조합, M*N)
(= CARTESIAN PRODUCT)

DBMS를 구현하기 위해 새롭게 만들어진 연산자

연산자 SQL 비고
SELECT WHERE
PROJECT SELECT
(NATURAL) JOIN NATURAL JOIN
INNER JOIN
OUTER JOIN
USING 조건절
ON 조건절
DIVIDE 현재 사용하지 않음

JOIN

n개의 테이블에서 필요 데이터 조회시 필요한 JOIN 조건은 대상(연산 기준) 테이블 개수 하나를 뺀 n-1개 이상이 필요하다. (= 피연산 테이블 개수가 n-1)

https://www.codeproject.com/articles/33052/visual-representation-of-sql-joins

기본 개념

EQUI JOIN

SELECT 테이블1.칼럼명, 테이블2.칼럼명, ... -- 유일성 보장을 위해 테이블명을 명시하는 습관을 들이자!
FROM 테이블1, 테이블2
WHERE 테이블1.칼럼명1 = 테이블2.칼럼명2;
 
 
/*ANSI/SQL 표준 방식 (INNER JOIN 명시)*/
SELECT 테이블1.칼럼명, 테이블2.칼럼명, ... -- 유일성 보장을 위해 테이블명을 명시하는 습관을 들이자!
FROM 테이블1 INNER JOIN 테이블2
ON 테이블1.칼럼명1 = 테이블2.칼럼명2;

SELECT P.PLAYER_NAME, T.TEAM_ID, STADIUM_NAME
FROM PLAYER P, TEAM T, STADIUM S
WHERE P.TEAM_ID = T.TEAM_ID
      AND T.STADIUM_ID = S.STADIUM_ID
ORDER BY PLAYER_NAME;

SELECT P.PLAYER_NAME, T.TEAM_ID, STADIUM_NAME
FROM PLAYER P INNER JOIN TEAM T
ON P.TEAM_ID = T.TEAM_ID
   INNER JOIN STADIUM S
   ON T.STADIUM_ID = S.STADIUM_ID
ORDER BY PLAYER_NAME;

Non EQUI JOIN

FROM 절 JOIN 형태

SQL Server의 경우 ON 조건절만 지원, NATURAL JOIN과 USING 조건절은 미지원,

INNER JOIN

/* WHERE절 JOIN 조건 */
SELECT 테이블.칼럼명, ...
FROM 테이블1[ [AS] 별칭], 테이블2[ [AS] 별칭]
WHERE 테이블1.칼럼명 = 테이블2.칼럼명;
 
 
/* FROM 절 JOIN 조건 */
SELECT 테이블.칼럼명, ...
FROM 테이블1[ [AS] 별칭] [INNER] JOIN 테이블2[ [AS] 별칭]
ON 테이블1.칼럼명 = 테이블2.칼럼명;

NATURAL JOIN

SELECT 칼럼명, ...
FROM 테이블1 NATURAL [INNER] JOIN 테이블2

OUTER JOIN

LEFT OUTER JOIN

SELECT 테이블명.칼럼명, ...
FROM 테이블명1[ [AS] 별칭] LEFT [OUTER] JOIN 테이블명2[ [AS] 별칭]
ON 테이블명1.칼럼명 = 테이블명2.칼럼명;

RIGHT OUTER JOIN

SELECT 테이블명.칼럼명, ...
FROM 테이블명1[ [AS] 별칭] RIGHT [OUTER] JOIN 테이블명2[ [AS] 별칭]
ON 테이블명1.칼럼명 = 테이블명2.칼럼명;

FULL OUTER JOIN

SELECT 테이블명.칼럼명, ...
FROM 테이블명1[ [AS] 별칭] FULL [OUTER] JOIN 테이블명2[ [AS] 별칭]
ON 테이블명1.칼럼명 = 테이블명2.칼럼명;

-- "LEFT/RIGHT JOIN 후 UNION"하면 아래 결과와 같다

-- SELECT 테이블명.칼럼명, ...
-- FROM 테이블명1[ [AS] 별칭] LEFT [OUTER] JOIN 테이블명2[ [AS] 별칭]
-- ON 테이블명1.칼럼명 = 테이블명2.칼럼명;
-- UNION
-- SELECT 테이블명.칼럼명, ...
-- FROM 테이블명1[ [AS] 별칭] RIGHT [OUTER] JOIN 테이블명2[ [AS] 별칭]
-- ON 테이블명1.칼럼명 = 테이블명2.칼럼명;

조건절

ON 조건절

WHERE, ORDER BY 혼용

SELECT T.TEAM_NAME, T.TEAM_ID, S.STADIUM_NAME
FROM TEAM T JOIN STADIUM S
ON T.TEAM_ID = S.HOMETEAM_ID
ORDER BY TEAM_ID;
 
SELECT T.TEAM_NAME, T.TEAM_ID, S.STADIUM_NAME
FROM TEAM T, STADIUM S
WHERE T.TEAM_ID = S.HOMETEAM_ID
ORDER BY TEAM_ID;

다중 Table JOIN

SELECT E.EMPNO, D.DEPTNO, D.DNAME, T.DNAME NEW_DNAME
FROM EMP E JOIN DEPT D
ON (E.DEPTNO = D.DEPTNO)
   JOIN DEPT_TEMP T
   ON E.DEPTNO = T.DEPTNO;
 
SELECT E.EMPNO, D.DEPTNO, D.DNAME, T.DNAME NEW_DNAME
FROM EMP E, DEPT D, DEPT_TEMP T
WHERE (E.DEPTNO = D.DEPTNO)
      AND (E.DEPTNO = T.DEPTNO);

USING 조건절

SELECT 칼럼명, ...
FROM 테이블1 [INNER] JOIN 테이블2
USING (칼럼명[, 칼럼명]);

CROSS JOIN

SELECT 테이블명.칼럼명, ...
FROM 테이블1[ [AS] 별칭] CROSS JOIN 테이블2[ [AS] 별칭];

Set Operator

집합 연산자

집합 연산자 설명 비고
UNION 합집합 (중복 제거) WHERE 절에 “IN”(같은 칼럼일때만), “OR” 연산자로 변환 가능
UNION ALL 합집합 (중복 허용) “NOT EXISTS”, “NOT IN” Sub Query로 변환 가능
INTERSECT 교집합 (공통 요소 추출) “EXISTS”, “IN” Sub Query로 변환 가능
EXCEPT
(Oracle : MINUS)
차집합 (앞SQL - (교집합))

SELECT ~ [HAVING ~]
집합_연산자
SELECT ~ [HAVING ~]
[ORDER BY ~]

Hierarchical Query

SELECT 칼럼명, ...
FROM 테이블명, ...
WHERE 조건, ...
START WITH 조건
CONNECT BY [NOCYCLE] 조건, ...
[ORDER SIBLINGS BY 칼럼명, ...]

Pseudo column

(Oracle 기준)

순방향 전개

SELECT LEVEL,
       LPAD('~', (LEVEL-1)*4) || EMPNO,
         --왼쪽 기준 "(LEVEL-1)*4"위치에 '~'삽입하고, EMPNO 칼럼을 덛붙인다.
       MGR,
       CONNECT_BY_ISLEAF --Leaf면 1, 아니면 0
FROM EMP
START WITH MGR IS NULL
CONNECT BY PRIOR EMPNO = MGR; --MGR→EMPNO

SELECT LEVEL,
       LPAD(EMPNO, LEVEL*4, '~'),
         --왼쪽 기준 "LEVEL*4"byte 길이로 출력하되 빈 자리는 '~'로 채운다.
       MGR,
       CONNECT_BY_ISLEAF --Leaf면 1, 아니면 0
FROM EMP
START WITH MGR IS NULL
CONNECT BY PRIOR EMPNO = MGR; --MGR→EMPNO

역방향 전개

SELECT LEVEL, LPAD(EMPNO, LEVEL*4, '~'), MGR, CONNECT_BY_ISLEAF
FROM EMP
START WITH EMPNO = '7876'
CONNECT BY EMPNO = PRIOR MGR;

Built-in function

(Oracle 기준)

SYS_CONNECT_BY_PATH

루트 데이터로부터 현재 전개할 데이터까지의 경로 표시

SYS_CONNECT_BY_PATH(칼럼, 경로분리자)

CONNECT_BY_ROOT

현재 전개할 데이터의 루트 데이터 표시.

CONNECT_BY_ROOT(칼럼)

SELF JOIN

SELECT 별칭1.칼럼명, 별칭2.칼럼명, ...
FROM 테이블명 [AS] 별칭1, 테이블명 [AS] 별칭2
WHERE 별칭1.칼럼명  = 별칭2.칼럼명