오라클에서도 이제 기초 과정에서 심화 과정인 JOIN을 배웠다. 물론 기초 단계인 GROUP BY, ORDER BY도 오전에 정리하고 시작했다.
아 집합함수도 배웠다.
그러면 먼저 집합함수 & GROUP BY, ORDER BY 부터 정리한 파일을 적어보겠다.
-- 2021-02-15 집합함수 (Group By)
/*
전체 데이터를 대상으로 통계를 구하는 프로그램
COUNT() : 전체 로우의 갯수(등록한)
= 로그인 처리
= 아이디 중복체크
형식)
COUNT(*) : NULL값을 포함
COUNT(column): NULL값을 제외
MAX() : 전체 데이터중에 최고값을 가지고 올때
= 자동증가 번호 생성 => MAX()+1
=========== 게시판 , 장바구니 , 예매하기
MIN() : 최소값
AVG() : 전체를 대상으로 평균 (column)
SUM() : 전체를 대상으로 합
RANK() : 순위 결정
1 2 3 3 5
DENSE_RANK() : 순위 결정
1 2 3 3 4
CUBE() : ROW단위 계산 + Column단위 계산
ROLLUP() : ROW단위 계산
# 주의점
일반 컬럼과는 동시에 사용이 불가능하다
단일행 함수와 동시에 사용이 불가능하다
예)
SELECT ename,count(*) FROM emp => (X)
SELECT count(*),substr() FROM emp => (X)
*/
-- COUNT() 함수 => 등록된 갯수
-- 사원이 몇명인지 확인
SELECT COUNT(*) FROM emp; -- NULL값을 포함
SELECT COUNT(comm) FROM emp; -- NULL값을 제외
SELECT COUNT(mgr) FROM emp;
-- 영화의 총갯수 = movie
SELECT COUNT(*) FROM movie;
-- 음악의 총갯수 = genie_music
SELECT COUNT(*) FROM genie_music;
/*
CREATE TABLE member(
id VARCHAR2(10),
pwd VARCHAR2(10)
);
INSERT INTO member VALUES('hong','1234');
INSERT INTO member VALUES('shim','1234');
COMMIT;
SELECT * FROM member;
*/
-- SELECT id FROM member WHERE id='kim';
-- 급여가 1500이상이고 3000이하인 사원의 갯수
-- sal>=1500 AND sal<=3000
-- sal BETWEEN 1500 AND 3000
SELECT COUNT(*) FROM emp
WHERE sal BETWEEN 1500 AND 3000;
SELECT COUNT(*) FROM emp
WHERE sal>=1500 AND sal<=3000;
-- 영화(Movie)에서 장르가 액션이 영화의 갯수를 확인
SELECT COUNT(*) FROM movie
WHERE genre LIKE '%액션%';
SELECT COUNT(*) FROM movie
WHERE REGEXP_LIKE(genre,'액션');
-- 웹사이트 => 검색
-- 음악(genie_music) 가수중에 방탄소년단의 노래가 몇개
SELECT singer FROM genie_music;
SELECT COUNT(*) FROM genie_music
WHERE singer='방탄소년단';
-- MAX => 최대값 => 형식 : MAX(column명)
SELECT MAX(sal),MIN(sal) FROM emp;
SELECT MAX(empno),MIN(empno) FROM emp;
-- AVG(평균) => 형식) AVG(column명)
-- emp(저장공간)에 등록된 사원의 급여의 평균을 가지고 온다
SELECT AVG(sal) FROM emp;
-- 사원중에 평균보다 급여가 많은 사원이 몇명인가?
SELECT COUNT(*) FROM emp
WHERE sal>2073;
SELECT COUNT(*) FROM emp
WHERE sal>(SELECT AVG(sal) FROM emp);
-- 서브쿼리
-- SUM(합) => 형식) SUM(column명)
SELECT SUM(sal),ROUND(AVG(sal),0) FROM emp;
-- 사원중에 사번이 홀수인 사원의 급여합 , 인원수 , 급여평균을 출력
SELECT SUM(sal),COUNT(*),AVG(sal) FROM emp
WHERE MOD(empno,2)=1;
-- deptno(부서번호) 부서별로 인원수,급여합,급여평균
-- 10 , 20 , 30
SELECT COUNT(*),SUM(sal),AVG(sal) FROM emp
WHERE deptno=10;
SELECT COUNT(*),SUM(sal),AVG(sal) FROM emp
WHERE deptno=20;
SELECT COUNT(*),SUM(sal),AVG(sal) FROM emp
WHERE deptno=30;
/*
SELECT deptno,COUNT(*),SUM(sal),AVG(sal) FROM emp
GROUP BY deptno;
*/
-- 누가 잘 묶는가? (메소드,클래스) => 함수
-- RANK => 형식) RANK() OVER(ORDER BY column명 ASC|DESC)
SELECT empno,ename,sal,RANK() OVER(ORDER BY sal DESC) "rank"
FROM emp;
SELECT empno,ename,sal,DENSE_RANK() OVER(ORDER BY sal DESC) "rank"
FROM emp;
-- 사원중에 입사한 순서로 등수를 설정 (이름,입사일, 등수)
SELECT ename,hiredate,RANK() OVER(ORDER BY hiredate ASC) "입사순"
FROM emp;
SELECT ename,hiredate,DENSE_RANK() OVER(ORDER BY hiredate ASC) "입사순"
FROM emp;
-- SORT
-- 사원의 이름을 A.B.C..
SELECT ename , RANK() OVER(ORDER BY ename ASC) "이름순"
FROM emp;
-- GROUP BY
SELECT * FROM emp;
SELECT * FROM emp
ORDER BY deptno ASC;
-- GROUP BY 컬럼명 (함수)
/*
1.그룹함수는 사용이 가능 , 그룹으로 설정된 컬럼이나 함수를 제외하고
나머지는 같이 사용이 불가능
SELECT deptno,ename,AVG(sal)
FROM emp
GROUP BY deptno;
2. 그룹컬럼에 별칭을 사용 할 수 없다
*/
-- 부서별 인원수 , 급여의 합
SELECT deptno,COUNT(*),SUM(sal)
FROM emp
GROUP BY deptno;
-- 입사년도별로 인원수 , 급여의 평균 (반올림)
-- 입사년도 1980
SELECT TO_CHAR(hiredate,'YYYY'), COUNT(*), ROUND(AVG(sal),0)
FROM emp
GROUP BY hiredate;
SELECT TO_CHAR(hiredate,'RRRR'),COUNT(*),ROUND(AVG(sal),0)
FROM emp
GROUP BY TO_CHAR(hiredate,'RRRR')
ORDER BY TO_CHAR(hiredate,'RRRR');
-- 입사년도별로 인원수 , 급여 평균을 출력 => 전체 급여평균보다 많은 그룹 출력)
SELECT TO_CHAR(hiredate,'RRRR'),COUNT(*),ROUND(AVG(sal),0)
FROM emp
--WHERE sal>(SELECT AVG(sal) FROM emp)
-- WHERE sal>AVG(sal)
GROUP BY TO_CHAR(hiredate,'RRRR')
HAVING AVG(sal)>2073;
SELECT TO_CHAR(hiredate, 'YYYY'),COUNT(*), ROUND(AVG(sal),0)
FROM emp
WHERE sal > (SELECT AVG(sal) FROM emp)
GROUP BY TO_CHAR(hiredate, 'YYYY')
ORDER BY TO_CHAR(hiredate, 'YYYY');
-- 영화(movie) 개봉년도별로 영화 갯수가 몇개인지?
SELECT SUBSTR(regdate,1,4),COUNT(*)
FROM movie
GROUP BY SUBSTR(regdate,1,4)
ORDER BY 1;
-- 뮤직(genie_music) 가수별 노래가 몇곡인지?
SELECT singer , COUNT(*)
FROM genie_music
GROUP BY singer;
/*
SELECT문장의 순서
================
SELECT
FROM
================ 필수
[
WHERE
===========
GROUP BY
HAVING =======> 그룹에 대한 조건 GROUP BY가 있는 경우에만 사용이 가능
===========
ORDER BY
]
*/
-- 이중 GROUP BY ==> 컬럼명,컬럼명
SELECT * FROM emp
ORDER BY deptno;
SELECT deptno,job,COUNT(*),SUM(sal),AVG(sal)
FROM emp
GROUP BY deptno,job
ORDER BY deptno;
-- 부서별 => 부서안에 입사년도별 , SUM(sal) , COUNT(*)
SELECT deptno,TO_CHAR(hiredate,'YYYY'),SUM(sal),COUNT(sal)
FROM emp
GROUP BY deptno,TO_CHAR(hiredate,'YYYY')
ORDER BY deptno;
-- ROLLUP.CUBE => 반드시 GROUP BY를 이용한다
SELECT deptno,job,COUNT(*)
FROM emp
GROUP BY ROLLUP(deptno,job);
SELECT NVL(deptno,0),NVL(job,'total'),COUNT(*)
FROM emp
GROUP BY CUBE(deptno,job);
-- 자바,오라클 => NULL값
-- ROLLUP => 뮤직 => 가수명 , 상태 , COUNT(*)
SELECT singer,state , COUNT(*)
FROM genie_music
GROUP BY ROLLUP(singer,state);
SELECT singer,state , COUNT(*)
FROM genie_music
GROUP BY CUBE(singer,state);
/*
1. GROUP BY (컴럼 , 함수(날짜 => DATE (TO_CHAR) , VARCHAR2 (SUBSTR))
2. 그룹에 대한 조건 => HAVING
3. 그룹 함수
= COUNT(*)
= MAX()
= AVG(),SUM()
= RANK() , DENSE_RANK()
4. ROLLUP , CUBE
==================== 기본 SQL
==================== 고급 SQL (JOIN,SUBQUERY)
= DDL
= TCL
= VIEW , SEQUENCE , INDEX , PL/SQL
= 오라클을 배우는 것이 아니라 => 자바에서 사용하는 오라클 SQL (2주)
*/
집합함수의 경우에는 자바 문법에서 배운 메소드들과 크게 다르지 않아서 자주 사용하는 것들만 외워두면 금세 익힐 것 같다. 특히 MAX(), COUNT(), SUM()과 같은 함수들이 자주 사용된다고 하니 이 부분을 집중적으로 공부하면 되지 않을까 싶다.
GROUP BY는 표시할 내용들을 그룹으로 묶어서 보여줄때 사용하는 함수이다.
이때 오름차순이나 내림차순으로 그룹을 표시하고 싶으면 ORDER BY를 사용해서 정리해주면 된다.
/*
page 18 => DBMS (면접)
page 19 => SQL
SQL
DML (SELECT,INSERT,UPDATE,DELETE)
DDL (CREATE , ALTER , DROP , RENAME, TRUNCATE)
TCL (COMMIT, ROLLBACK)
page 26 => SELECT 문법
======= 출력 , 컬럼 대신 , 테이블 대신
========== ==========
스칼라 서브쿼리 , 인라인 뷰
SELECT * | column1,column2...
=== ==================
page 26 page 29
FROM table명|View명|SELECT ~~
[
WHERE
GROUP BY
HAVING
ORDER BY
]
page 33 => 별칭 => 함수로 출력 , 컬럼명이 길다
= 컬럼명 "별칭"
= 컬럼명 as 별칭
page 34 => 중복을 제거 : DISTINCT (컬럼 앞에 사용)
SELECT DISTINCT deptno ~~
page 37 => 문자열 결합 : ||
=====
'' => 문자,문자열,날짜 (숫자 => ''을 붙여도 상관이 없다 (자동형변환)=> 속도가 늦다)
page 36 => ORDER BY
1. 정렬 (오라클은 빈공간에 데이터를 저장하기 때문에 순서가 존재하지 않는다)
2. ORDER BY 컬럼번호,컬럼명,함수 ASC|DESC => ASC는 생략이 가능
=======
SELECT * FROM emp
ORDER BY 1 => empno
3. 이중 정렬 =>() ,() => 댓글 , 답변형 게시판
=== ==
page 40 => WHERE (조건문)
====== 연산자
산술 연산자 : 주로 SELECT뒤에
나머지 연산자 : boolean => WHERE 문장 뒤에
===========
비교연산자 : = , !=(<>) , < , > , <= ,>=
논리연산자 : AND , OR
대입연산자 : = (UPDATE)
NOT,NULL,BETWEEN,IN(OR가 여러개),LIKE(%,_)
=== ===== 연산처리가 안된다 => IS NULL , IS NOT NULL
NOT IN()
NOT BETWEEN
NOT LIKE
NOT (sal>= AND sal<=)
page 41 => 문자 조회는 '' , 대소문자 구분 (page 43)
page 45 => 연산자 종류 (45~56)
page 56 => ORDER BY
page 59 => 집합 연산자(테이블 2개에서 데이터를 얻어오기)
UNION : 데이터 전체를 가지고 온다 (단 중복은 제거)
A : 12345
B : 34567 ==> 1234567
UNION ALL : 데이터 전체를 가지고 온다 (FULL OUTER JOIN)
A : 12345
B : 34567 ==> 1234534567
INTERSECT : 교집합 (INNER JOIN)
A : 12345
B : 34567 ==> 345
MINUS : 같은 데이터 제외하고 나머지
A : 12345
B : 34567 ==> A-B :12 , B-A : 67
INTERSECT+(A-B) : LEFT OUTER JOIN
INSERSECT+(B-A) : RIGHT OUTER JOIN
page 68 : 단일행 , 집합함수
page 69 : 단일행
=====
문자함수 , 숫자함수 , 날짜함수 ,변환함수 ,일반함수
page 70 : 문자함수
SUBSTR() : 75 page
LENGTH() : 73 page
INSTR() : 76 page
RPAD () : 81 page
REGEXP_LIKE() : 124 page
page 86 : 숫자함수
ROUND() : 반올림 => 86 page
TRUNC() : 버림 => 86 page
MOD() : 나머지 => 87 page
CEIL(): 올림 => 87 page
page 89 : 날짜함수
SYSDATE : 시스템의 날짜 , 시간 => 90 page
MONTHS_BETWEEN() => 91 page
page 99 : 형변환함수
TO_CHAR () :문자열 변환 (page 102(년도,월,일,시간,분,초)
(page 107 (숫자변환))
page 99 => 오라클에서 사용하는 데이터형
문자형 (CHAR , VARCHAR2,CLOB) => String
숫자형 (NUMBER) => int ,double
날짜형 (DATE,TIMESTAMP) => java.util.Date
page 110 : 일반함수
NVL() : NULL값일 경우에 대체하는 함수 : 110page
DECODE() : 다중 조건문 : 113page
집합함수
page 158 => COUNT(159),SUM(159),AVG(160),MAX(160),RANK(198) , CUBE(176),ROLLUP(167)
===============================================
page 162 => GROUP BY (162~166)
*/
-- SELECT * FROM genie_music;
/*
SELECT * FROM emp;
SELECT ename,empno,hiredate
FROM emp
ORDER BY 1;
*/
오라클에서 중요한 함수들과 책 페이지를 같이 적어주신 필기이다. 여기 나온 함수들을 위주로 공부하면 되지 않을까 싶다.
-- 2021-02-15(4장 - 조인 : SQL고급과정)
/*
2개이상의 테이블로부터 데이터 수집 경우 : 조인(JOIN)
======
2개이상의 SQL문장을 합쳐서 데이터 수집 : 서브쿼리 ===> SELECT
================
조인
1) 테이블 한개이상에서 필요한 데이터를 찾아오기
============
2) 조인의 종류
= INNER JOIN => 교집합 (값이 같은 것이 있는 경우)
= EQUI_JOIN
1. Oracle JOIN
2. ANSI JOIN
3. NATURAL JOIN
4. JOIN~USING
= NON_EQUI_JOIN
1. Oracle JOIN
2. ANSI JOIN
= OUTER JOIN
= LEFT OUTER JOIN
= RIGHT OUTER JOIN
= FULL OUTER JOIN
*/
SELECT * FROM emp;
SELECT * FROM dept;
/*
SELECT * FROM salgrade;
CREATE TABLE salgrade(
grade NUMBER,
losal NUMBER,
hisal NUMBER
);
INSERT INTO salgrade VALUES(1,700,1200);
INSERT INTO salgrade VALUES(2,1201,1400);
INSERT INTO salgrade VALUES(3,1401,2000);
INSERT INTO salgrade VALUES(4,2001,3000);
INSERT INTO salgrade VALUES(5,3001,9000);
COMMIT;
*/
/*
INNER JOIN
1) EQUI_JOIN
= Oracle JOIN (A,B) (오라클에서만 사용이 가능)
SELECT A.col1,A.col2,B.col1,B.col2
FROM A,B
WHERE A.col3=B.col3;
= ANSI JOIN(표준화=>모든 데이터베이스 공동으로 사용이 가능)
SELECT A.col1,A.col2,B.col1,B.col2
FROM A (INNER) JOIN B
ON A.col3=B.col3;
*/
-- emp (사번 , 이름 ,직위, 입사일) , dept (부서명,근무지) => deptno
SELECT empno,ename,job,hiredate,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno;
-- 테이블의 별칭을 사용 (테이블명이 글자수의 제한)
SELECT empno,ename,job,hiredate,dname,loc
FROM emp e,dept d
WHERE e.deptno=d.deptno;
-- ANSI
SELECT empno,ename,job,hiredate,dname,loc
FROM emp INNER JOIN dept
ON emp.deptno=dept.deptno;
SELECT empno,ename,job,hiredate,dname,loc
FROM emp JOIN dept
ON emp.deptno=dept.deptno;
------------------------------------- 테이블이 같은 컬럼명이 존재해야 한다 (다른 컬럼을 비교해서 사용:값이 동일)
-- 자연조인
SELECT empno,ename,job,hiredate,dname,loc
FROM emp NATURAL JOIN dept;
-- JOIN _ USING
SELECT empno,ename,job,hiredate,dname,loc
FROM emp JOIN dept USING(deptno);
--------------------------------------------
/*
테이블 => 컬럼명이 다른 경우에는 컬럼명만 사용해도 된다 , 같은 컬럼명이면 어느 테이블에서 가지고 올 것인지 설정
*/
SELECT empno,ename,job,hiredate,dname,loc,e.deptno
FROM emp e,dept d
WHERE e.deptno=d.deptno;
/*
NON EQUI_JOIN : JOIN~USING,NATURAL JOIN은 사용 할 수 없다
============== =이 아닌 다른 연산자를 사용할 경우에 (BETWEEN, >= AND <=)
EQUI_JOIN : (연산자 = ) => 단점 (연산자를 사용 했기 때문에 NULL값이 있는 경우에는 처리가 불가능하다)
*/
SELECT ename,sal,hiredate,grade
FROM emp,salgrade
WHERE sal BETWEEN losal AND hisal;
/*
emp(사원정보)
empno : 사번
ename : 이름
job : 직위
mgr : 사수번호
hiredate : 입사일
sal : 급여
comm : 성과급
deptno : 부서번호
dept(부서정보)
deptno : 부서번호
dname : 부서명
loc : 근무지
salgrade(급여등급)
grade : 등급 (호봉)
losal : 최저급여
hisal : 최대급여
*/
-- 조인 조건 , 개인 조건
-- 이름,직위,입사일,급여,부서명,근무지 출력 => 사번이 7788인 사원의 정보출력
SELECT ename,job,hiredate,sal,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno
AND empno=7788;
-- 위에 Oracle JOIN => ANSI JOIN으로 변경
SELECT ename,job,hiredate,sal,dname,loc
FROM emp JOIN dept
ON emp.deptno=dept.deptno
AND empno=7788;
-- emp(ename,job,hiredate,sal) , dept(dname,loc) , salgrade(grade)
-- 1. Oracle JOIN
SELECT ename,job,hiredate,sal,dname,loc,grade
FROM emp,dept,salgrade
WHERE emp.deptno=dept.deptno
AND sal BETWEEN losal AND hisal;
-- 2. ANSI JOIN
SELECT ename,job,hiredate,sal,dname,loc,grade
FROM emp
JOIN dept
ON emp.deptno=dept.deptno
JOIN salgrade
ON sal BETWEEN losal AND hisal;
-- 한개의 테이블에서 조인이 가능 => 반드시 테이블에 별칭을 사용한다
-- emp(본인 이름),emp(사수 이름)
/*
조인 조건
1. 컬럼명이 같다 (같은 값을 가지고 있다)
===========
primary key , foreign key
2. 컬럼명이 다르다 (같은 값을 가지고 있다) => 게시판 <==> 댓글
*/
-- self join
SELECT e1.ename "본인 이름",e2.ename "사수 이름"
FROM emp e1,emp e2
WHERE e1.mgr=e2.empno;
-- 조건검색에 컬럼명이 다르면 NATURAL JOIN,JOIN~USING은 사용이 불가능하다
-- emp (사번 , 이름 , 직위 , 성과급 , 급여) , dept(부서명 , 근무지) => JOIN , 성괴급을 받는 사원에 대해서만 출력
SELECT empno,ename,job,comm,sal,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno
AND comm IS NOT NULL AND comm<>0;
-- ANSI JOIN
SELECT empno,ename,job,comm,sal,dname,loc
FROM emp JOIN dept
ON emp.deptno=dept.deptno
AND comm IS NOT NULL AND comm<>0;
-- emp (사번 , 이름 ,직위 , 성과급, 급여) , dept(부서명,근무지 )=> JOIN , 이름중에 A를 포함하고 있는 사원의 정보를 출력
-- Oracle Join
SELECT empno,ename,job,comm,sal,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno
AND ename LIKE '%A%';
-- ANSI JOIN
SELECT empno,ename,job,comm,sal,dname,loc
FROM emp JOIN dept
ON emp.deptno=dept.deptno
AND ename LIKE '%A%';
-- emp (사번 , 이름 ,직위 , 성과급, 급여) , dept(부서명,근무지 )=> JOIN , 81년에 입사한 사원에 대해서 출력
SELECT empno,ename,job,comm,sal,hiredate,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno
AND SUBSTR(hiredate,1,2)=81;
SELECT empno,ename,job,comm,sal,hiredate,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno
AND hiredate LIKE '81%';
SELECT empno,ename,job,comm,sal,hiredate,dname,loc
FROM emp JOIN dept
ON emp.deptno=dept.deptno
AND hiredate LIKE '81%';
/*
자바 : 포함 클래스
사용자 요청 SQL
브라우저(HTML) <========> 자바(파이썬) <=========> 오라클
전송 실행 결과
*/
-- OUTER JOIN (INNER JOIN + 알파) => null값을 포함해서 데이터를 가지고 온다
/*
= LEFT OUTER JOIN
1. Oracle JOIN (A,B => col1,col2,col3(공통된 데이터가 있다))
A.col3 B.col3
1 1
2 2
3 3
4 (출력을 할 수 없다)
SELECT A.col1,A.col2,B.col1,B.col2
FROM A,B
WHERE A.col3=B.col3(+)
2. ANSI JOIN
SELECT A.col1,A.col2,B.col1,B.col2
FROM A LEFT OUTER JOIN B
===============
ON A.col3=B.col3
= RIGHT OUTER JOIN
1. Oracle JOIN
SELECT A.col1,A.col2,B.col1,B.col2
FROM A,B
WHERE A.col3(+)=B.col3
2. ANSI JOIN
SELECT A.col1,A.col2,B.col1,B.col2
FROM A RIGHT OUTER JOIN B
===============
ON A.col3=B.col3
= FULL OUTER JOIN(사용빈도가 별로 없다)
1. ANSI JOIN
SELECT A.col1,A.col2,B.col1,B.col2
FROM A FULL OUTER JOIN B
===============
ON A.col3=B.col3
*/
-- RIGHT
SELECT empno,ename,job,dept.deptno,dname,loc
FROM emp,dept
WHERE emp.deptno(+)=dept.deptno;
SELECT empno,ename,job,dept.deptno,dname,loc
FROM emp RIGHT OUTER JOIN dept
ON emp.deptno=dept.deptno;
SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1, emp e2
WHERE e1.mgr=e2.empno(+);
SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1 LEFT OUTER JOIN emp e2
ON e1.mgr=e2.empno;
SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1 FULL OUTER JOIN emp e2
ON e1.mgr=e2.empno;
-- 14 (KING,BLAKE,JONES , FORD, SCOTT , CLARK)
JOIN부터는 조금 헷갈리기 시작했다. 특히 INNER JOIN은 그냥저냥 잘 이해한거 같은데 OUTER JOIN이 나온 순간부터 또 헷갈리기 시작했다. 내가 왼쪽 오른쪽을 안그래도 잘 구분을 못해가지고...
일단 정리를 해보면 같은 COLUMN명이 있는 테이블들을 조합할때는 EQUI_JOIN을 사용한다.
대표적인 예시는 아래와 같다.
SELECT empno,ename,job,hiredate,dname,loc
FROM emp,dept
WHERE emp.deptno=dept.deptno;
deptno column이 같기 때문에 위와 같이 적어줄 수 있었다. 위는 oracle join 방식이고
ANSI JOIN은 아래와 같이 써주면 된다.
SELECT empno,ename,job,hiredate,dname,loc
FROM emp INNER JOIN dept
ON emp.deptno=dept.deptno;
크게 다른 점은 없고, 그냥 INNER JOIN을 써주고 WHERE 대신 ON을 써준다는 점을 잘 기억하면 된다.
NON EQUI_JOIN은 = 을 쓰지 않는 JOIN 방식이다.
대표적인 예로 아래 코드를 들 수 있다.
SELECT ename,sal,hiredate,grade
FROM emp,salgrade
WHERE sal BETWEEN losal AND hisal;
emp와 salgrade는 같은 column을 공유하지 않는다. 그렇기 때문에 between and와 같은 연산기호를 사용해서 값을 가져올수 있도록 하고 있다.
한개의 테이블에서 JOIN이 가능한 경우도 있다. 이 경우를 SELF_JOIN 이라고 한다. 대신 꼭 테이블 별칭을 사용해서 값들을 구분해서 가져와야한다.
SELECT e1.ename "본인 이름",e2.ename "사수 이름"
FROM emp e1,emp e2
WHERE e1.mgr=e2.empno;
이런식으로 사용이 가능하다. mgr은 사수의 사번이기 때문에 WHERE 조건절을 저렇게 걸어주었다.
나를 헷갈리게 만들었던 OUTER_JOIN
-- RIGHT
SELECT empno,ename,job,dept.deptno,dname,loc
FROM emp,dept
WHERE emp.deptno(+)=dept.deptno;
SELECT empno,ename,job,dept.deptno,dname,loc
FROM emp RIGHT OUTER JOIN dept
ON emp.deptno=dept.deptno;
SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1, emp e2
WHERE e1.mgr=e2.empno(+);
SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1 LEFT OUTER JOIN emp e2
ON e1.mgr=e2.empno;
SELECT e1.ename "본인" , e2.ename "사수"
FROM emp e1 FULL OUTER JOIN emp e2
ON e1.mgr=e2.empno;
-- 14 (KING,BLAKE,JONES , FORD, SCOTT , CLARK)
그러니까 나중에 볼 내가 이해하기 쉽게 정리를 해보자면
왼쪽에 정보가 더 많아서 오른쪽의 테이블이 따라 붙어야 하는 경우를 LEFT_JOIN,
오른쪽에 정보가 더 많아서 왼쪽의 테이블이 따라 붙어야 하는 경우를 RIGHT_JOIN이라고 해준다.
그리고 내용이 더 적어서 따라 붙어야 하는 쪽에 (+)를 표기해주면 된다.
이렇게 정리해서 이해하니 생각보다 엄청 복잡한 개념은 아니었다.
'programming > Gukbi' 카테고리의 다른 글
국비 교육 37일차 - DML, 제약조건 (0) | 2021.02.17 |
---|---|
국비 교육 36일차 - JOIN, JAVA-ORACLE 연동 (0) | 2021.02.16 |
국비 교육 34일차 - ORACLE (0) | 2021.02.10 |
국비 교육 33일차 - DB (0) | 2021.02.09 |
국비 교육 32일차 - DB (0) | 2021.02.08 |