join은 다음과 같이 분류한다.
1. 내부 join(=등가, equi join) (inner join)
1) 자연 join
2) on join
3) using join
- 비등가(not equi=on, using) join
2. 외부 join (outer join)
3. 교차 join (cross join)
4. 셀프 join (self join)
etc. semi join, anti join
......
@@@(다 알아야 하나..)
하지만, 대부분 우리가 쓰는 join은 equi join에서 대부분 사용한다.
cross join(실제 테이블에서는 이렇게 하면 위험함!)
--TSQL JOIN
SELECT *
FROM TAB01, TAB02;
--또는(ANSI JOIN), 권장하는 방식
SELECT *
FROM TAB01 CROSS JOIN TAB02;
equi join(등가 조인)
내부 조인 ⊃ 등가 조인
SELECT *
FROM TAB01, TAB02
--TAB01 GNO = PRIMARY KEY(바뀌지 않는 키)
--TAB02 GNO = FOREIGNER KEY(외부 키)
--등가 JOIN: PK와 FK를 등가 연산하는 것
WHERE TAB01.GNO = TAB02.GNO;
TABLE 마다 별명을 붙이는 것을 권장함.
SELECT *
FROM TAB01 T1, TAB02 T2
WHERE T1.GNO = T2.GNO;
--FIELD 선택 출력
SELECT NAME, T1.GNO, SAL, GRADE
FROM TAB01 T1, TAB02 T2
WHERE T1.GNO = T2.GNO;
--INNER JOIN 이용
SELECT NAME, T1.GNO, SAL, GRADE
FROM TAB01 T1 INNER JOIN TAB02 T2
ON T1.GNO = T2.GNO;
JOIN 조건별 분류
SELECT NAME, T1.GNO, SAL, GRADE
--FROM 뒤에 있는 내용은 모두 JOIN 조건
FROM TAB01 T1, TAB02 T2
--WHERE 뒤에 있는 내용은 일반 조건
WHERE T1.GNO = T2.GNO
AND ROWNUM <= 2 --출력 갯수 제한
AND SAL >= 200
;
등가 JOIN과 비등가 JOIN
SELECT NAME, T1.GNO, SAL, GRADE
FROM TAB01 T1, TAB02 T2
--등가 JOIN(=이용한 JOIN)
WHERE T1.GNO = 1
--비등가 JOIN(부등호 조건 이용한 JOIN)
AND T1.SAL BETWEEN T2.LOSAL AND T2.HISAL;
외부 JOIN(OUTER JOIN)
--등가 연산
SELECT T1.ID, NAME, AGE
FROM TAB01 T1, TAB02 T2
WHERE T1.ID = T2.ID;
--OUTER JOIN 1
SELECT T1.ID, NAME, AGE
FROM TAB01 T1, TAB02 T2
WHERE T1.ID = T2.ID(+);
-- +: 왼쪽(T1) 테이블 내용 모두 출력
--OUTER JOIN 2
SELECT T1.ID, NAME, AGE
FROM TAB01 T1, TAB02 T2
WHERE T1.ID(+) = T2.ID;
-- 오른쪽(T2) 테이블 내용 모두 출력
JOIN 다시 정리.
--LEFT JOIN
SELECT T1.ID, NAME, AGE
FROM TAB01 T1 LEFT JOIN TAB02 T2
ON T1.ID = T2.ID;
--RIGHT JOIN
SELECT T1.ID, NAME, AGE
FROM TAB01 T1 RIGHT JOIN TAB02 T2
ON T1.ID = T2.ID;
--FULL OUTER JOIN
SELECT T1.ID, NAME, AGE
FROM TAB01 T1 FULL OUTER JOIN TAB02 T2
ON T1.ID = T2.ID;
--INNER JOIN
SELECT T1.ID, NAME, AGE
FROM TAB01 T1 INNER JOIN TAB02 T2
ON T1.ID = T2.ID;
겹치는 부분 제거하는 JOIN
--LEFT JOIN 중 겹치는 부분 제거
SELECT T1.ID, NAME, AGE
FROM TAB01 T1 LEFT JOIN TAB02 T2
ON T1.ID = T2.ID
WHERE T2.ID IS NULL;
--RIGHT JOIN 중 겹치는 부분 제거
SELECT T1.ID, NAME, AGE
FROM TAB01 T1 RIGHT JOIN TAB02 T2
ON T1.ID = T2.ID
WHERE T1.ID IS NULL;
-- FULL OUTER JOIN 중 겹치는 부분 제거
SELECT T1.ID, NAME, AGE
FROM TAB01 T1 FULL OUTER JOIN TAB02 T2
ON T1.ID = T2.ID
WHERE T1.ID IS NULL
OR T2.ID IS NULL;
NATURAL JOIN: EQUI(등가) JOIN의 Upgrade Version
USING JOIN: NATURAL JOIN의 Upgrade Version
결국 USING JOIN 또는 ON JOIN을 사용함.
하나를 골라 계속 쓰는 것 권장.
ON JOIN: USING과 동일하지만, 등가와 비등가 모두 사용함.
NATURAL JOIN
SELECT *
FROM TAB01 T1 NATURAL JOIN TAB02 T2;
--공통으로 걸린 것은 DB가 알아서 찾게 함
USING JOIN
등가 JOIN 대신하는 방식, 다중 사용 가능
SELECT ID, NAME, AGE
FROM TAB01 T1 JOIN TAB02 T2 USING(ID)
WHERE AGE >= 200;
ON JOIN
가장 넓은 범위. 등가 및 비등가 모두 사용 가능.
SEMIJOIN
ex) 세계의 모든 국가 데이터가 있는데
우리 반 학생들이 가고 싶은 국가는 5개밖에 없다.
이 국가의 리스트를 보고 싶을 때 사용한다.
--SEMIJOIN
SELECT *
FROM TAB02
WHERE TAB02.DEPT IN(
SELECT DEPT
FROM TAB01);
--EXIST가 속도가 더 빠름.
SELECT *
FROM TAB02 T2
WHERE EXISTS(
SELECT *
FROM TAB01 T1
WHERE T1.DEPT = T2.DEPT
);
ex) 다음과 같은 테이블이 2개 있다.(탕슉은 무시하자..)
음식번호 중국집 메뉴
NUM MENU
---------- ----------
1 짜장
2 우동
3 냉면
4 짬뽕
5 탕슉
주문번호 판매 갯수 판매 가격 음식번호
ORDERNUM VALUE PRICE NUM
---------- ---------- ---------- ----------
1 2 3000 2
2 2 3000 3
3 2 3000 1
4 2 3000 2
5 2 3000 3
6 2 3000 1
7 2 3000 2
8 2 3000 3
여기서 사장님이 이렇게 물었다.
"오늘 무슨 음식 팔았노?"
이러면 우린 오늘 짜장, 우동, 냉면만 팔았다고 말하도록 데이터가 출력되어야 한다.
SEMIJOIN을 이용한 방법은 다음과 같다.
SELECT *
FROM MENU M
WHERE M.NUM IN(
SELECT NUM
FROM ORDERS);
반대로 "오늘 뭐 안팔렸지?"는 다음과 같다.
여기서 NOT EXIST를 EXIST로 바꾸면 앞 결과와 같아진다.
SELECT *
FROM MENU M
WHERE NOT EXISTS(
SELECT *
FROM ORDERS O
WHERE O.NUM = M.NUM
);
등가 JOIN 및 DISTINCT를 통해서도 같은 결과를 낼 수 있다.
하지만, 실제로 DB에서 연산을 할 시에는 효율이 떨어지므로 이렇게는 쓰지 않는다.
SELECT
DISTINCT MENU, M.NUM
FROM MENU M, ORDERS O
WHERE M.NUM = O.NUM
ORDER BY NUM;
무슨 음식을 몇 개나 팔았는지 추가하려면, 다음과 같이 하면 COUNT로 출력된다.
(SELECT 안 서브쿼리로 COUNT 추가)
SELECT M.NUM, M.MENU,
(SELECT COUNT(*)
FROM ORDERS S
WHERE S.NUM = M.NUM)
AS COUNT
FROM MENU M
WHERE EXISTS(
SELECT *
FROM ORDERS S
WHERE S.NUM = M.NUM)
ORDER BY NUM;
'Oracle' 카테고리의 다른 글
Oracle - DML(데이터 조작: 추가·수정·삭제) (0) | 2020.06.03 |
---|---|
Oracle - SubQuery (0) | 2020.06.03 |
Oracle EMP Table 예시 (0) | 2020.06.01 |
Oracle 기본 Query문 4 (0) | 2020.06.01 |
Oracle 기본 Query문 3 (0) | 2020.05.27 |