오라클은 사용자를 생성하면 데이터베이스도 자동으로 생성한다

1. 사용자
2. DB
3. 테이블

-----------

SYNONYM은
CREATE PUBLIC SYNONYM EMP FOR SCOTT.EMP; (다른 사용자의 테이블을 시노님으로 가져오기)
위처럼 쓰면 FROM EMP; 처럼 이용해도 가져와진다.

위처럼 쓰지 않으면 다른테이블을 가져올때 항상
FROM SCOTT.EMP; 처럼 사용해야 한다

---------------------------------

뷰의 핵심은 동기화

외부직원에게 테이블의 민감한 정보를 제외하고 제공할때 복제해서주면 동기화의 문제와 다시합칠때 문제가 있다

VIEW를 이용하면 정보를 은닉하여 보여주고 싶은 것만 보여주고 동기화도 자동으로 된다

 

---------------------------------

CRUD (필수 꼭외울 것)

INSERT - C (create)

SELECT - R (read)

UPDATE - U

DELETE - D

--------------------------------

SELECT * 
FROM EMP; 를 하면 DB에 검색을 바로 하는게 아니라 DBMS(오라클)를 검색한다
1. 파싱 ( 코드 구문분석)
2. 데이터딕셔너리에게 메타데이터를 물어본다 (EMP테이블이 있어? ENAME라는 컬럼이 있어?)
3. 있으면 DB(램을 검색하고 램에 없으면 하드에서 램으로 올려서 검색)
(한번 수행했던 쿼리는 다시 수행하면 파싱이나 딕셔너리접근을 하지않아서 빠르게 출력된다)

 

--------------------------------

CPU - 캐시메모리 - 램

이면 캐시메모리가 캐시 역할

CPU - 램 - 하드디스크

이면 램이 캐시 역할

 

CPU가격은 캐시메모리가 정한다(속도가 매우 빠르기때문)

---------------------------------

최근 프로그래밍에서 속도증가는 자료구조 등 보다 하드디스크접근(I/O)을 줄이는 것에 집중되어 있다

디스크 접근(I/O)을 줄이는 방법
1.캐시메모리를 늘리기 / 메모리에 자주쓰는 데이터를 올리는 기법
2.시퀀셜 엑세스 기법
3.랜덤엑세스 기법

1번이 가장 중요

 

2.시퀀셜 엑세스 기법

순서대로 블록 전체를 다 읽어서 필요한 데이터를 찾아낸다.(풀스캔)

풀스캔 - 찾을 데이터가 많으면 많을수록 유리해진다

 

3.랜덤 엑세스 기법 (프라이머리 키)

필요한 블록만 하나씩 가져오는 것

데이터가 적으면 적을수록 유리해진다

통상 15%이내의 데이터를 검색할 때 시퀀셜보다 랜덤 엑세스가 유리하다

----------------------------

클러스터 - 군집화

클러스터링 팩터 전략
데이터를 아무곳에나 놓는 것이 아니라 비슷한것은 모아두는 것(검색시 속도향상)

------------------------------

 

 

 

'Database > OracleSQL' 카테고리의 다른 글

200408  (0) 2020.04.08
오라클 서브쿼리 문제  (0) 2020.04.03
오라클 서브쿼리, IN, EXISTS 차이  (0) 2020.04.02
오라클 DML, INSERT, SELECT, UPDATE, DELETE  (0) 2020.04.02
오라클 VIEW  (0) 2020.04.02

서브쿼리

SELECT *
FROM EMP
WHERE SAL > 800;

800을 서브쿼리로 바꾸기

SELECT *
FROM EMP
WHERE SAL > 
(
    SELECT SAL
    FROM EMP
    WHERE ENAME = 'SMITH'
);

 

 

조건이 1개, 비교값도 1개일 경우

SELECT *
FROM EMP
WHERE SAL > 
(
    SELECT SAL
    FROM EMP
    WHERE ENAME = 'SMITH'
);

 

조건이 1개, 비교값이 여러개일 경우

SELECT *
FROM EMP
WHERE SAL IN 
(
    SELECT SAL
    FROM EMP
    WHERE JOB = 'MANAGER'
);


--위 코드는 아래와 같다

SELECT *
FROM EMP
WHERE SAL IN (2975, 2850, 2450);

 

 

STUDENT 테이블과 DEPARTMENT 테이블을 사용하여 
'서진수'학생과 1전공(DEPTNO1)이 동일한 학생들의 
이름과 1전공 이름을 출력하세요

 

먼저 서진수 학생의  전공번호를 확인한다

SELECT DEPTNO1
FROM STUDENT
WHERE NAME = '서진수';

 

전공이 101인 학생의 이름과 전공이름을 출력한다

SELECT S.NAME STUD_NAME, d.dname DEPT_NAME
FROM STUDENT S, DEPARTMENT D
WHERE D.DEPTNO = 101 AND S.DEPTNO1 = d.deptno;

 

101자리에 서브쿼리를 넣는다

SELECT S.NAME STUD_NAME, d.dname DEPT_NAME
FROM STUDENT S, DEPARTMENT D
WHERE D.DEPTNO =
(
SELECT DEPTNO1
FROM STUDENT
WHERE NAME = '서진수'
) AND S.DEPTNO1 = d.deptno;

 

 

PROFESSOR 테이블과 DEPARTMENT 테이블을 조회하여

'주승재'교수보다 나중에 입사한 사람의 이름과 입사일, 학과명을 출력하세요.

 

먼저 주승재 교수의 입사일을 확인한다

SELECT HIREDATE
FROM PROFESSOR
WHERE NAME = '주승재';

 

위의 테이블을 서브쿼리하여 이름과 입사일 학과명을 출력한다

SELECT P.NAME , P.HIREDATE, d.dname
FROM PROFESSOR P, DEPARTMENT D
WHERE HIREDATE > 
(
SELECT HIREDATE
FROM PROFESSOR
WHERE NAME = '주승재'
)
AND p.deptno = d.deptno;

 

STUDENT 테이블에서 1전공(DEPTNO1)이 201번인 학과의

평균 몸무게보다 몸무게가 많은 학생들의 이름과 몸무게를 출력하세요.

 

먼저 201번 학과의 평균 몸무게를 검색한다

SELECT AVG(WEIGHT)
FROM STUDENT
WHERE DEPTNO1 = 201
GROUP BY DEPTNO1;

 

위의 테이블을 서브쿼리하여 학생들의 이름과 몸무게를 출력한다

SELECT NAME, WEIGHT
FROM STUDENT
WHERE WEIGHT >
(
SELECT AVG(WEIGHT)
FROM STUDENT
WHERE DEPTNO1 = 201
GROUP BY DEPTNO1
);

 

EMP2 테이블을 사용하여 전체 직원 중 '과장' 직급의 최소 연봉자보다
연봉이 높은 사람의 이름과 직급, 연봉을 출력하세요.
단, 연봉 출력 형식은 아래와 같이 천 단위 구분 기호화 $표시를 하세요.

 

먼저 EMP2 테이블의 과장직급의 최소 연봉을 구한다

    SELECT MIN(PAY)  -- MIN함수는 월급을 찾는다
    FROM EMP2
    WHERE POSITION = '과장'

 

4900만원이 최소치이므로 WHERE으로 그 이상인 사람들을 찾을 수 있다.

SELECT NAME, POSITION, to_char(pay, '$999,999,999')
FROM EMP2
WHERE pay > 49000000;

 

서브쿼리로 처음 코드를 넣으면

SELECT NAME, POSITION, to_char(pay, '$999,999,999')
FROM EMP2
WHERE pay >
(
    SELECT MIN(PAY)
    FROM EMP2
    WHERE POSITION = '과장'
);

 

 

EMP2 테이블과 DEPT2 테이블을 조회하여 각 부서별 평균 연봉을 구하고
그중에서 평균 연봉이 가장 적은 부서의 평균 연봉보다
적게받는 직원들의 부서명, 직원명, 연봉을 출력하세요.

 

먼저 각부서별 평균연봉을 구한다

SELECT AVG(PAY)
FROM EMP2
GROUP BY  DEPTNO
ORDER BY  AVG(PAY);

 

위의 코드를 서브쿼리하여서 1번째 것을 출력

SELECT *
FROM
(
  SELECT AVG(PAY)
  FROM EMP2
  GROUP BY  DEPTNO
  ORDER BY  AVG(PAY)
)
WHERE ROWNUM = 1;

 

그리고 출력할 것들을 SELECT 정리하고 25000000자리에 위 코드를 서브쿼리한다

SELECT DEPT2.DNAME, EMP2.NAME, TO_CHAR(EMP2.PAY, '$999,999,999') SALARY
FROM EMP2, DEPT2
WHERE PAY < 25000000 AND EMP2.DEPTNO = DEPT2.DCODE;

 

SELECT DEPT2.DNAME, EMP2.NAME, TO_CHAR(EMP2.PAY, '$999,999,999') SALARY
FROM EMP2, DEPT2
WHERE PAY < 
(
  SELECT *
  FROM
  (
    SELECT AVG(PAY)
    FROM EMP2
    GROUP BY  DEPTNO
    ORDER BY  AVG(PAY)
  )
  WHERE ROWNUM = 1
) 
AND EMP2.DEPTNO = DEPT2.DCODE;

 

 

IN 과  EXISTS의 차이

IN 은 서브쿼리 데이터를 WHERE 오른쪽의 DEPTNO 와 비교해서 같은 값인 경우에만 출력한다

    SELECT DEPTNO
    FROM DEPT
    WHERE DEPTNO = 20;

20이 출력

 

DEPTNO가 20인 모든 데이터를 출력

SELECT * FROM DEPT
WHERE DEPTNO IN (
    SELECT DEPTNO
    FROM DEPT
    WHERE DEPTNO = 20
    );

 

EXISTS는 서브쿼리 데이터가 있으면 메인 쿼리를 모두 실행하고, 없으면 아예 실행하지 않는다

SELECT * FROM DEPT
WHERE EXISTS (
    SELECT DEPTNO
    FROM DEPT
    WHERE DEPTNO = 20
    );

 

SELECT * FROM DEPT
WHERE EXISTS (
    SELECT DEPTNO
    FROM DEPT
    WHERE DEPTNO = 50
    );

 

 

 

'Database > OracleSQL' 카테고리의 다른 글

오라클 서브쿼리 문제  (0) 2020.04.03
200402 // SYNONYM, VIEW, CRUD, 인덱스 INDEX, , 클러스터링  (0) 2020.04.02
오라클 DML, INSERT, SELECT, UPDATE, DELETE  (0) 2020.04.02
오라클 VIEW  (0) 2020.04.02
오라클 ANSI JOIN  (0) 2020.04.02

DML

CRUD (필수 꼭외울 것)

INSERT - C (create)

SELECT - R (read)

UPDATE - U

DELETE - D

 

INSERT

데이터를 삽입할 때 사용

INSERT INTO dept2 (dcode, dname, pdept, area)
VALUES(9000, 'temp_1',1006, 'Temp Area');

 

제대로 들어갔는지 확인 해본다

SELECT *
FROM dept2;

 

날짜의 경우 INSERT 할때 

ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD:HH24:MI:SS';

위 코드를 이용하여 형식을 바꾼뒤 '2014-10-23' 으로 넣거나

요소 입력시 TO_DATE를 이용하여 입력하여야한다.

자동으로 입력하려면 SYSDATE를 요소에 입력한다.

TO_DATE('2014-10-23', 'YYYY-MM-DD')

 

 

음수값 입력하기

CREATE TABLE t_minus(
no1 NUMBER,
no2 NUMBER(3),
no3 NUMBER(3,2));
INSERT INTO t_minus VALUES(1, 1, 1);

INSERT INTO t_minus VALUES(1.1, 1.1, 1.1);

INSERT INTO t_minus VALUES(-1.1, -1.1, -1.1);
SELECT * FROM t_minus;

NUMBER(3) - 정수자리를 3자리 (999) 로 지정

NUMBER(3, 2) - 정수자리를 3자리 (999) , 소수자리를 2자리 (0.99) 로 지정 

 

INSERT와 서브 쿼리를 사용하여 여러 행 입력하기

먼저 PROFESSOR 테이블을 복사하여 PROFESSOR3를 만든다

--INSERT와 서브쿼리를 사용하여 여러행 입력하기
CREATE TABLE professor3
AS
SELECT * FROM professor
WHERE 1 = 2; -- 아무데이터도 넣지 않기위해 무조건 틀린 조건이 나오도록 함

 

확인을 위해 select 해본다

SELECT *
FROM professor3;

의도 대로 데이터가 없는 테이블이 생성 되었다

 

 

서브쿼리로 여러건의 데이터를 한꺼번에 입력해본다

INSERT INTO professor3
SELECT * FROM professor;

 

professor3을 다시 확인해보면

SELECT *
FROM professor3;

자료들이 정상적으로 입력되어 있다

 

조건을 걸어서 입력하려면

INSERT INTO professor3
SELECT * FROM professor
WHERE PROFNO > 4000;

위와 같이 아래에 조건을 넣으면 된다 ( PROFNO가 4000번을 초과하는 행만 넣기)

 

 

INSERT ALL을 이용한 여러 테이블에 여러행 입력하기

먼저 테스트 테이블을 생성

CREATE TABLE prof_3
(
profno NUMBER,
name VARCHAR2(25)
);

CREATE TABLE prof_4
(
profno NUMBER,
name VARCHAR2(25)
);

 

다른 테이블의 데이터를 가져와서 입력

INSERT ALL
WHEN profno BETWEEN 1000 AND 1999 THEN INTO prof_3 VALUES(profno, name)
WHEN profno BETWEEN 2000 AND 2999 THEN INTO prof_4 VALUES(profno, name)
SELECT profno, name -- 모든 profno, name를 가져오기
FROM professor;

 

또는 아래와 같이 WHERE를 써도 된다

INSERT ALL
INTO prof_3 VALUES (profno, name)
INTO prof_3 VALUES (profno, name)
SELECT profno, name
FROM professor
WHERE profno BETWEEN 3000 AND 3999;

 

 

UPDATE

기존데이터를 다른 데이터로 변경 할때 사용

문법

UPDATE table
SET column = value
WHERE 조건;

 

 

직급이 조교수인 교수들의 BONUS를 200만원으로 인상

UPDATE professor
SET bonus = 200
WHERE position = '조교수';

 

확인해본다

SELECT *
FROM professor;

 

 

차범철 교수의 직급과 동일한 직급을 가진 교수들 중 현재 급여가 250만원이 안되는 교수들의 급여를 15%인상

UPDATE professor
SET pay = pay * 1.15
WHERE position =
(
SELECT position
FROM professor
WHERE name = '차범철'
)
and pay < 250;

 

UPDATE 조인

일반적인 UPDATE가 아닌 다른 테이블과 조인을 하는 UPDATE에 대해서 살펴본다

 

일반적인 UPDATE

UPDATE emp
SET sal = (sal + sal*0.1)
WHERE JOB = 'CLERK';

 

 

일반적인 UPDATE 조인

UPDATE emp E
SET sal = (sal + sal*0.1)
WHERE EXISTS
(
    SELECT 1 FROM DEPT D
    WHERE D.LOC = 'DALLAS' AND E.DEPTNO = D.DEPTNO
);

#여기서 서브쿼리안에  E.DEPTNO를 쓸 수 있는 것은 
코드를 실행할 때 코드안의 모든 테이블을 가장 먼저 불러오기 때문이다
그렇기 때문에 서브쿼리 밖에 있는 emp E를 서브쿼리 안에서 쓸 수 있는 것

 

 

테스트를 위한 테이블 생성

CREATE TABLE DEPT_HIST
(
    EMPNO NUMBER(4),
    APPOINTSEQNO NUMBER(4),
    DEPTNO NUMBER(2),
    APPOINTDD DATE
);

 

 

부서 번호가 20인 사원 발령 부서 번호 99로 데이터를 INSERT

INSERT INTO DEPT_HIST
SELECT EMPNO, 1 APPOINTSEQNO, 99 DEPTNO, SYSDATE APPOINTDD
FROM emp
WHERE DEPTNO = 20;

COMMIT;

 

 

EMP 테이블에 존재하지 않는 사원번호 2건을 INSERT

INSERT INTO DEPT_HIST VALUES (9322, 1, 99, SYSDATE);
INSERT INTO DEPT_HIST VALUES (9322, 1, 99, SYSDATE);

COMMIT;

 

 

잘못된 부서번호 99를 20으로 UPDATE

SELECT e.empno, e.deptno tobe_deptno, d.deptno asis_deptno
FROM emp e, dept_hist d
WHERE e.empno = d.empno;

 

UPDATE DEPT_HIST D
SET d.deptno = 
(
SELECT e.deptno FROM EMP e
WHERE e.empno = d.empno
);

COMMIT;

 

SELECT *
FROM DEPT_HIST;

 

 

DELETE

데이터를 삭제할 때 사용

DELETE FROM dept2
WHERE dcode >= 9000 AND dcode <= 9999;

 

DELETE는 데이터를 삭제하는 것이지만, 눈에 보이지 않게만 할뿐 데이터는 저장소에 저장되어 있다.
특별한 툴(BBED 등)을 이용하여 복구 할 수 있다

 

VIEW

뷰의 핵심은 은닉과 동기화

외부직원에게 테이블의 민감한 정보를 제외하고 제공할때 복제해서주면 동기화의 문제와 다시합칠때 문제가 있다

VIEW를 이용하면 정보를 은닉하여 보여주고 싶은 것만 보여주고 동기화도 자동으로 된다

 

원본

SELECT *
FROM student;

 

테이블 잘라내서 복제하기

CREATE TABLE student2
AS
SELECT studno, name, id, grade, height, weight, deptno1, deptno2, profno
FROM student;

 

VIEW 이용

관리자에서 VIEW 권한을 줌

--DCL
GRANT CREATE VIEW TO SCOTT;

 

SCOTT에서 뷰 사용

CREATE OR REPLACE VIEW STUDENT_VIEW
AS
SELECT studno, name, id, grade, height, weight, deptno1, deptno2, profno
FROM student;

 

SELECT 해보면 잘라진 테이블이 출력된다

SELECT *
FROM STUDENT_VIEW;

 

테스트를 위해 JUMIN 을 널이아님을 체크 해제한다

 

STUDENT_VIEW에 자료 넣기

INSERT INTO STUDENT_VIEW(studno, name, id, grade, height, weight, deptno1, deptno2, profno)
VALUES(9716, '홍길동', 'jaybon', 1, 170, 65, 101, 201, 1001);

 

확인해보기

SELECT *
FROM STUDENT_VIEW;

 

같은 데이터를 넣으면 오류가난다

INSERT INTO STUDENT_VIEW(studno, name, id, grade, height, weight, deptno1, deptno2, profno)
VALUES(9716, '홍길동', 'jaybon', 1, 170, 65, 101, 201, 1001);

 

스키마를 확인한다

 

.

 

ANSI JOIN

-- 오라클 조인
SELECT E.EMPNO, E.ENAME, E.DEPTNO, D.DNAME
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO;


-- ANSI 조인
SELECT E.EMPNO, E.ENAME, E.DEPTNO, D.DNAME
FROM EMP E JOIN DEPT D      --콤마를 JOIN으로
ON E.DEPTNO = D.DEPTNO;     --WHERE를 ON으로( WHERE가 있으나 조인할때는 ON을 쓴다)

 

ANSI JOIN에서도 WHERE 사용 가능

-- ANSI 조인

SELECT E.EMPNO, E.ENAME, E.DEPTNO, D.DNAME
FROM EMP E JOIN DEPT D
ON E.DEPTNO = D.DEPTNO AND D.DEPTNO = 10;  --AND 사용가능


SELECT E.EMPNO, E.ENAME, E.DEPTNO, D.DNAME
FROM EMP E JOIN DEPT D
ON E.DEPTNO = D.DEPTNO
WHERE D.DEPTNO = 10;   --ANSI 조인에도 ON 아래에 WHERE를 쓸 수 있다

 

 

오라클과 ANSI의 OUTER JOIN

-- 오라클 조인
SELECT *
FROM BOARD B, REPLY R
WHERE B.ID = R.BOARDID;

-- ANSI 조인
SELECT *
FROM BOARD B LEFT OUTER JOIN REPLY R
ON B.ID = R.BOARDID;

 

 

FULL OUTER JOIN

FULL OUTER JOIN은 오라클에서는 되지 않고 ANSI 를 써야한다

--오라클 조인
SELECT *
FROM BOARD B, REPLY R
WHERE B.ID(+) = R.BOARDID(+);

 

--ANSI 조인
SELECT *
FROM BOARD B FULL OUTER JOIN REPLY R
ON B.ID = R.BOARDID;

.

카티션 곱

-- 카티션 곱 ( 데이터 3종류의 테이블과 2종류의 테이블이 있으면 6개의 데이터가 생성됨)
SELECT *
FROM emp, dept
ORDER BY ENAME;

 

ANSI 조인 - 표준이기때문에 어떤 DB에서도 사용할 수 있다

-------------------------

MYSQL 을 패키지에 묶어서 팔면 라이센스비가 나오고

고객사 컴퓨터에 세팅해주고 패키지에 빼면 비용이 들지 않는다

------------------------

EQUI Join (이퀄 조인) = inner Join / 동일 조인 / 조인(기본적으로 사용하는 조인이기 때문)

-------------------------

데이터베이스에서는 (여러가지 자료형을 저장하는) CLASS타입이 없다! (중요)

테이블의 하나의 레코드(행의 모든 데이터)을 오브젝트로 보면 된다 

-------------------------

테이블끼리 연결되어있다는 것을 외래키를 통해서 확인 할 수 있다

기본키는 모든테이블에 다 있어야한다

그 기본키를 다른 테이블에 외래키로 사용하는 것이 좋다

해당기본키를 벗어난 값을 외래키 열에 넣으면 제약조건을 벗어나게 된다

 

조인시 FROM 할 때 후행 테이블의 PK를 조인할 때 연산이 줄어든다

 

 

 

 

 

 

 

 

 

 

'Database > OracleSQL' 카테고리의 다른 글

오라클 VIEW  (0) 2020.04.02
오라클 ANSI JOIN  (0) 2020.04.02
오라클 조인, INNER JOIN, OUTER JOIN  (0) 2020.04.01
오라클 ROWNUM, RANK, DENSE_RANK, ROW_NUMBER, PARTITION  (0) 2020.04.01
200326 OLTP, OLAP ROLLUP  (0) 2020.03.26

오라클조인

INNER JOIN

--오라클 조인문법
SELECT e.ename, e.deptno, d.dname, d.deptno
FROM emp E, dept D
where E.deptno = D.deptno;

 

 

RIGHT OUTER JOIN (외부 조인)

(+)를 붙이면
(+)가 붙지 않은 쪽의 DEPTNO를 있는대로 다뽑고 
(+)가 붙은 쪽은 빈 곳은 NULL값이 출력된다

SELECT *
FROM emp e, dept d
WHERE e.deptno(+) = d.deptno;

 

 

LEFT OUTER JOIN

 

기본키를 가진 것을 뒤쪽으로 보내는 것이 작동 속도를 빠르게 한다

 

 

학생과 담당교수를 PROFNO로 JOIN하기

SELECT s.name "학생명", p.name "교수명",s.profno, p.position
FROM student s, professor p
where s.profno = p.profno
ORDER BY p.profno;

 

 

조인 테이블들 만들어보기

 

테이블 이름을 클래스라고 생각하고 파스칼 표기법으로 생성

 

 

 

Board테이블

 

 

워크시트에서 테이블 만들기

-- DDL (테이블 삭제drop, 수정alter, 생성create)
CREATE TABLE Reply(
    id number,
    content VARCHAR2(200) not null,
    boardId number,
    userId number,
    CONSTRAINT REPLY_PK PRIMARY KEY (id),
    CONSTRAINT REPLY_FK_BOARD_ID FOREIGN KEY (boardId) REFERENCES Board (id),
    CONSTRAINT REPLY_FK_USER_ID FOREIGN KEY (userId) REFERENCES Users (id)
);

 

시퀀스 생성

CREATE SEQUENCE users_seq
INCREMENT BY 1
START WITH 1;


CREATE SEQUENCE board_seq
INCREMENT BY 1
START WITH 1;


CREATE SEQUENCE reply_seq
INCREMENT BY 1
START WITH 1;

 

데이터 입력하기

-- Users, Board, Reply
-- DML (데이터 조작어)
INSERT INTO USERS(ID, USERNAME, EMAIL) -- (ID, USERNAME, EMAIL) 다넣을거면 안적어도되지만, 순서를 바꾸려면 넣어야한다
VALUES (USERS_SEQ.nextval, 'ssar', 'ssar@nate.com'); -- USERS_SEQ.nextval (시퀀스)를 쓰면 숫자가 자동으로 붙는다

INSERT INTO USERS(ID, USERNAME, EMAIL)
VALUES (USERS_SEQ.nextval, 'love', 'love@nate.com');

INSERT INTO USERS(ID, USERNAME, EMAIL)
VALUES (USERS_SEQ.nextval, 'cos', 'cos@nate.com');

commit;

 

INSERT INTO BOARD(ID, TITLE, CONTENT, USERID)
VALUES(BOARD_SEQ.nextval, '오라클 1강', 'DDL이란?', 1);

INSERT INTO BOARD(ID, TITLE, CONTENT, USERID)
VALUES(BOARD_SEQ.nextval, '오라클 2강', 'DML이란?', 1);

INSERT INTO BOARD(ID, TITLE, CONTENT, USERID)
VALUES(BOARD_SEQ.nextval, '오라클 3강', 'DCL이란?', 2);

INSERT INTO BOARD(ID, TITLE, CONTENT, USERID)
VALUES(BOARD_SEQ.nextval, '오라클 4강', 'DQL이란?', 1);

COMMIT;

 

INSERT INTO REPLY(ID, CONTENT, BOARDID, USERID)
VALUES(REPLY_SEQ.nextval, '재밌어요', 1, 1);

INSERT INTO REPLY(ID, CONTENT, BOARDID, USERID)
VALUES(REPLY_SEQ.nextval, '진짜 재밌어요', 1, 2);

COMMIT;

 

-- 조인
SELECT *
FROM USERS U, BOARD B
WHERE U.ID = B.USERID;

-- 3번 유저가 나오게 조인
SELECT *
FROM USERS U, BOARD B
WHERE U.ID = B.USERID(+);

 

-- 댓글 적은사람 안적은사람 모두 찾기
SELECT *
FROM USERS U, REPLY R
WHERE U.ID = R.USERID(+);

-- 댓글 안적은 사람 찾기(WHERE이용)
SELECT *
FROM USERS U, REPLY R
WHERE U.ID = R.USERID(+)
AND R.ID IS NULL;

-- 댓글 안적은 사람 찾기(MINUS이용)
SELECT *
FROM USERS U, REPLY R
WHERE U.ID = R.USERID(+)

MINUS

SELECT *
FROM USERS U, REPLY R
WHERE U.ID = R.USERID;

 

-- 댓글 적은 사람만 찾기
SELECT *
FROM USERS U, REPLY R
WHERE U.ID = R.USERID;


-- 댓글 적은 사람만 찾기(INTERSECT이용)
SELECT *
FROM USERS U, REPLY R
WHERE U.ID = R.USERID(+)

INTERSECT

SELECT *
FROM USERS U, REPLY R
WHERE U.ID = R.USERID;

 

 

-- 그룹함수가 있으면 나머지 요소를 그룹바이에 넣어라
SELECT B.ID, B.TITLE, B.USERID, COUNT(R.ID) "댓글수"
FROM BOARD B, REPLY R
WHERE B.ID = R.BOARDID(+)
GROUP BY B.ID, B.TITLE, B.USERID;

-- 서브쿼리로
SELECT ID, TITLE, USERID, (SELECT COUNT(*) FROM REPLY WHERE BOARDID = B.ID) "댓글수"
FROM BOARD B;

 

 

-- 유저아이디를 유저네임으로 바꾸고 USERS 나오게
SELECT B.ID, B.TITLE, u.username, COUNT(R.ID) "댓글수"
FROM BOARD B, REPLY R, USERS U
WHERE B.ID = R.BOARDID(+) AND u.id(+) = b.userid
GROUP BY B.ID, B.TITLE, u.username
ORDER BY B.ID;

 

 

테이블 시퀀스 지우기

--테이블 지우기
DELETE FROM BOARD;

--시퀀스 지우기
DROP SEQUENCE BOARD_SEQ;

 

A

 

순위매기기

ROWNUM으로 만들면 같은 금액도 순위가 넘어간다

SELECT ename, sal, rownum
FROM
(
SELECT ename, sal
FROM emp
);

 

 

ROWNUM으로 순위 합치기

 + LAG OVER 함수는 순서를 미루는 함수

SELECT ename, s1, s2, DECODE(s1, s2, NO-1, NO)
FROM
(
SELECT ename, sal "S1", LAG(sal, 1, 0) OVER(ORDER BY sal DESC) "S2", ROWNUM "NO"
FROM
(
SELECT ename, sal
FROM emp           -- 프롬으로 퍼올릴때 로우넘 번호가 매겨진다
ORDER BY Sal desc
)
);

 

 

RANK OVER를 이용한 순위합치기

SELECT ename, sal, RANK() OVER (ORDER BY sal DESC)
FROM emp;

 

 

RANK() OVER 를 이용해서 학생 키 순위 구하기

SELECT name, height, RANK() OVER (ORDER BY height DESC) "RANK"
FROM student;

 

 

학년별 키순위를 구하시오

union all 방식

SELECT name, grade, height, RANK() OVER (ORDER BY height DESC) "RANK"
FROM student
WHERE grade = 1

UNION ALL

SELECT name, grade, height, RANK() OVER (ORDER BY height DESC) "RANK"
FROM student
WHERE grade = 2

UNION ALL

SELECT name, grade, height, RANK() OVER (ORDER BY height DESC) "RANK"
FROM student
WHERE grade = 3

UNION ALL

SELECT name, grade, height, RANK() OVER (ORDER BY height DESC) "RANK"
FROM student
WHERE grade = 4;

 

PARTITION 방식

SELECT name, grade, height, RANK() OVER (PARTITION BY grade ORDER BY height DESC) "RANK"
FROM student;

 

 

RANK, DENSE_RANK, ROW_NUMBER 비교

SELECT empno, ename, job, sal,
    RANK() OVER (ORDER BY sal DESC) sal_rank,
    DENSE_RANK() OVER (ORDER BY sal DESC) sal_dense_rank,
    ROW_NUMBER() OVER (ORDER BY sal DESC) sal_row_num
FROM emp;

 

--------------------------

+ Recent posts