본문 바로가기

   
Programming/ORACLE

7일차!

반응형

# 다중행 서브쿼리

 

- 여러 행을 반환하는 서브쿼리

- 다중 연산자(in, any, all) 사용한다.

 

* IN : 조회된 결과들 중에서 임의의 하나와 일치하는

 

* ANY : 조회된 결과의 값과 비교. 이중 하나라도 조건이 만족하면

 

SALARY < ANY(100, 200, 300)     최대값보다 작은

SALARY > ANY(100, 200, 300)     최소값보다 큰것. 조건들중 아무거나 하나보다 크면 찾아진다.

SALARY = ANY(100, 200. 300)     IN 동일

 

* ALL : 조회된 결과의 모든 값의 비교

 

SALARY < ALL(100, 200, 300)     최소값보다 작은 . 모든 값보다 작은 . 100보다 작은것

SALARY > ALL(100, 200, 300)     최대값보다 . 모든 값보다 큰것. 300보다 큰것

 

* 다중 컬럼 서브쿼리

 

SELECT NAME, GRADE, HEIGHT

FROM STUDENT

WHERE (GRADE, HEIGHT) = (SELECT 컬럼/표현식, 컬럼/표현식 FROM STUDENT);

- 서브쿼리의 값이 2개가 온다.

 

SELECT NAME, GRADE, HEIGHT

FROM STUDENT

WHERE (GRADE, HEIGHT) IN (SELECT 컬럼/표현식, 컬럼/표현식 FROM STUDENT);

 

-- 다중행 서브쿼리

-- 부서별 최저 급여 표시하기

SELECT MIN(SALARY)

FROM EMPLOYEES

GROUP BY DEPARTMENT_ID;

 

SELECT LAST_NAME, DEPARTMENT_ID, SALARY

FROM EMPLOYEES

WHERE SALARY IN (6900, 2500, 7000);

 

-- 부서별 최저급여와 급여와 같은 사원의 이름, 부서번호, 급여 출력

SELECT LAST_NAME, DEPARTMENT_ID, SALARY

FROM EMPLOYEES

WHERE SALARY IN (SELECT MIN(SALARY) FROM EMPLOYEES GROUP BY DEPARTMENT_ID);

-- IN 연산자는 결과값이 하나 이상 나오는 경우 사용가능하다

SELECT LAST_NAME, DEPARTMENT_ID, SALARY

FROM EMPLOYEES

WHERE SALARY IN (SELECT MIN(SALARY) FROM EMPLOYEES);

 

-- 다중행 서브쿼리

-- ALL, ANY보다는 IN 많이 쓰인다.

-- ANY 위험한 연산자

SELECT LAST_NAME, DEPARTMENT_ID, SALARY

FROM EMPLOYEES

WHERE SALARY > ALL(15000, 20000);

 

SELECT LAST_NAME, DEPARTMENT_ID, SALARY

FROM EMPLOYEES

WHERE SALARY > ANY(15000, 20000);

 

-- 다중 컬럼 서브쿼리

-- 비교해야하는 값이 2

-- 학년별 최고

SELECT GRADE, MAX(HEIGHT)

FROM STUDENT

GROUP BY GRADE;

 

-- 학년별 최고 키를 가진 학생의 이름과 학년, 키를 표시

-- 학년과 키를 같이 비교

SELECT NAME, GRADE, HEIGHT

FROM STUDENT

WHERE (GRADE, HEIGHT) IN (SELECT GRADE, MAX(HEIGHT) FROM STUDENT GROUP BY GRADE);

 

* 스칼라 서브쿼리

 

-- 부서별 인원수 계산하기

-- SELECT 절에도 서브쿼리가 가능하다

SELECT B.DEPARTMENT_ID, (SELECT COUNT(*) FROM EMPLOYEES A WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID) CNT

FROM DEPARTMENTS B;

 

-- King 사원의 사원번호, 이름, 부서아이디, 부서명을 표시

-- 1) JOIN 경우

SELECT E.EMPLOYEE_ID, E.LAST_NAME, D.DEPARTMENT_ID, D.DEPARTMENT_NAME

FROM EMPLOYEES E, DEPARTMENTS D

WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID

AND E.LAST_NAME = 'King';

 

-- 2) 서브쿼리 사용

-- JOIN 많을 수록 성능이 저하 -> 스칼라 서브쿼리

-- 조인 없이 특정 테이블의 값을 가져오는 방법 -> 값을 가져오는 쿼리를 SELECT문에 적으면 된다.

SELECT E.EMPLOYEE_ID, E.LAST_NAME, E.DEPARTMENT_ID,

      (SELECT D.DEPARTMENT_NAME

      FROM DEPARTMENTS D

      WHERE D.DEPARTMENT_ID = E.DEPARTMENT_ID) 부서명

FROM EMPLOYEES E

WHERE E.LAST_NAME = 'King';

 

-- 부서별 사원수를 스칼라 서브쿼리로 구하기

SELECT A.DEPARTMENT_ID,

      (SELECT COUNT(*)

      FROM EMPLOYEES B

      WHERE B.DEPARTMENT_ID = A.DEPARTMENT_ID) 사원수 

FROM DEPARTMENTS A;

 

 

-- 고객의 포인트가 50만점을 넘을 경우 산악자전거를 선물로 제공

-- 고객의 포인트가 50만점 이하일 떄는 샴푸세트를 제공

-- 고객번호, 고객이름, 포인트, 선물

-- 이런 쿼리가 있다 정도만 파악

-- 2) 포인트 추가하기

SELECT GNO, GNAME, POINT,

  CASE

  WHEN POINT > 500000

  THEN

  (SELECT GNAME

  FROM GIFT WHERE POINT + 200000 > G_START

  AND POINT + 200000 <= G_END) -- 2) GIFT POINT에다 20만점 점수 추가

  WHEN POINT <= 500000

  THEN

  (SELECT GNAME

  FROM GIFT WHERE POINT + 100000 > G_START

  AND POINT + 100000 <= G_END)

  END AS 경품

FROM GOGAK;

 

 

* VIEW

 

- 가상의 테이블

- 쿼리를 (SELECT)실행하면 얻어지는 결과는 항상 테이블의 형태다.

=> 얻어진 결과(테이블) 갖고 값을 읽어 있다.

 

- 부서번호별 사원수로 얻어진 결과를 FROM 절의 가상테이블로 지정하여 쿼리문 작성

 

* 시퀀스(SEQUENCE)

 

- 연속적인 인련번호를 만들어주는 기능

- 무조건 앞의 번호보다 값이 나온다

- 오라클에서 제공하는 객체

- ) 은행의 번호표발행기기 같은 역할

- 캐쉬 : 성능(속도)향상을 위해 자주 사용될 것같은 것을 미리 저장해놓는 기능

- 기본적으로 시퀀스를 20개를 만들어 놓는다

- 중복되는 번호를 없게 만들기 위해 사용하는

=> 행을 대표하는 값이 있다

 

CREATE SEQUENCE 시퀀스명

INCREAMENT BY 1

START WITH 1

NOCACHE;

 

-- BOOK_NO 일련번호 부여

INSERT INTO SAMPLE_BOOK

    (BOOK_NO, BOOK_TITLE, BOOK_AUTHOR, BOOK_PUBLISHER,

     BOOK_PRICE, BOOK_PUBDATE, BOOK_SUMMARY)

VALUES(MY_SEQ.NEXTVAL, '어린왕자', '쌩떽쥐베리','한성출판사', 10000, SYSDATE, '어른 동화책');

 

-- ROWNUM 행에다가 숫자를 붙이는

SELECT ROWNUM, BOOK_NO, BOOK_TITLE

FROM SAMPLE_BOOK;

 

-- 정렬된 순서에도 번호를 매길수 있다.

-- 페이징 처리에 활용

=> 예를 들어 주문번호들 중에서 몇개가 빠져있을수 있기 때문에 정렬후 새로운 번호를 부여하여 값을 처리

 

SELECT ROW_NUMBER() OVER(ORDER BY BOOK_NO DESC) 일련번호, BOOK_NO, BOOK_TITLE

FROM SAMPLE_BOOK;

 

 

-- 다중행 서브쿼리

-- 부서별 최저 급여 표시하기

SELECT MIN(SALARY)

FROM EMPLOYEES

GROUP BY DEPARTMENT_ID;

 

SELECT LAST_NAME, DEPARTMENT_ID, SALARY

FROM EMPLOYEES

WHERE SALARY IN (6900, 2500, 7000);

 

-- 부서별 최저급여와 급여와 같은 사원의 이름, 부서번호, 급여 출력

SELECT E.LAST_NAME, D.DEPARTMENT_ID, E.SALARY

FROM EMPLOYEES E JOIN DEPARTMENTS D

ON E.DEPARTMENT_ID = D.DEPARTMENT_ID

WHERE E.SALARY IN (SELECT MIN(SALARY) FROM EMPLOYEES GROUP BY DEPARTMENT_ID);

-- IN 연산자는 결과값이 하나 이상 나오는 경우 사용가능하다

 

 

-- 다중행 서브쿼리

-- ALL, ANY보다는 IN 많이 쓰인다.

-- ANY 위험한 연산자

SELECT LAST_NAME, DEPARTMENT_ID, SALARY

FROM EMPLOYEES

WHERE SALARY > ALL(15000, 20000);

 

SELECT LAST_NAME, DEPARTMENT_ID, SALARY

FROM EMPLOYEES

WHERE SALARY > ANY(15000, 20000);

 

-- 다중 컬럼 서브쿼리

-- 비교해야하는 값이 2

-- 학년별 최고

SELECT GRADE, MAX(HEIGHT)

FROM STUDENT

GROUP BY GRADE;

 

-- 학년별 최고 키를 가진 학생의 이름과 학년, 키를 표시

-- 학년과 키를 같이 비교

SELECT NAME, GRADE, HEIGHT

FROM STUDENT

WHERE (GRADE, HEIGHT) IN (SELECT GRADE, MAX(HEIGHT) FROM STUDENT GROUP BY GRADE);

 

-- 부서별 인원수 계산하기

-- SELECT 절에도 서브쿼리가 가능하다(스칼라 서브쿼리)

--조인을 많이해야할때 스칼라서브 쿼리를 이용한다.

SELECT B.DEPARTMENT_ID, (SELECT COUNT(*) FROM EMPLOYEES A WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID) CNT

FROM DEPARTMENTS B;

 

-- King 사원의 사원번호, 이름, 부서아이디, 부서명을 표시

-- 1) JOIN 경우

SELECT E.EMPLOYEE_ID, E.LAST_NAME, D.DEPARTMENT_ID, D.DEPARTMENT_NAME

FROM EMPLOYEES E, DEPARTMENTS D

WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID

AND E.LAST_NAME = 'King';

 

-- 2) 서브쿼리 사용

-- JOIN 많을 수록 성능이 저하 -> 스칼라 서브쿼리

-- 조인 없이 특정 테이블의 값을 가져오는 방법 -> 값을 가져오는 쿼리를 SELECT문에 적으면 된다.

SELECT E.EMPLOYEE_ID, E.LAST_NAME, E.DEPARTMENT_ID,

      (SELECT D.DEPARTMENT_NAME

      FROM DEPARTMENTS D

      WHERE D.DEPARTMENT_ID = E.DEPARTMENT_ID) 부서명

FROM EMPLOYEES E

WHERE E.LAST_NAME = 'King';

 

-- 부서별 사원수를 스칼라 서브쿼리로 구하기

SELECT A.DEPARTMENT_ID,

      (SELECT COUNT(*)

      FROM EMPLOYEES B

      WHERE B.DEPARTMENT_ID = A.DEPARTMENT_ID) 사원수 

FROM DEPARTMENTS A;

 

-- 고객의 포인트가 50만점을 넘을 경우 산악자전거를 선물로 제공

-- 고객의 포인트가 50만점 이하일 떄는 샴푸세트를 제공

-- 고객번호, 고객이름, 포인트, 선물

-- 이런 쿼리가 있다 정도만 파악

-- 2) 포인트 추가하기

SELECT GNO, GNAME, POINT,

  CASE

  WHEN POINT > 500000

  THEN

  (SELECT GNAME

  FROM GIFT WHERE POINT + 200000 > G_START

  AND POINT + 200000 <= G_END) -- 2) GIFT POINT에다 20만점 점수 추가

  WHEN POINT <= 500000

  THEN

  (SELECT GNAME

  FROM GIFT WHERE POINT + 100000 > G_START

  AND POINT + 100000 <= G_END)

  END AS 경품

FROM GOGAK;

 

-- VIEW (가상의 테이블)

-- SELECT 실행 결과를 가상의 테이블로 FROM 절에 넣어 쿼리문 작성

SELECT DEPARTMENT_ID, CNT

FROM (SELECT DEPARTMENT_ID, COUNT(*) CNT

      FROM EMPLOYEES

      GROUP BY DEPARTMENT_ID)

WHERE CNT>30;

 

-- 시퀀스(SEQUENCE)

-- 시퀀스에서 새로운 일련번호 발행함기

SELECT MY_SEQ.CURRVAL

FROM DUAL;

 

-- BOOK_NO 일련번호 부여

INSERT INTO SAMPLE_BOOK

    (BOOK_NO, BOOK_TITLE, BOOK_AUTHOR, BOOK_PUBLISHER,

     BOOK_PRICE, BOOK_PUBDATE, BOOK_SUMMARY)

VALUES(MY_SEQ.NEXTVAL, '어린왕자', '쌩떽쥐베리','한성출판사', 10000, SYSDATE, '어른 동화책');

 

-- ROWNUM 행에다가 숫자를 붙이는

SELECT ROWNUM, BOOK_NO, BOOK_TITLE

FROM SAMPLE_BOOK;

 

-- 정렬된 순서에도 번호를 매길수 있다.

-- 페이징 처리에 활용

SELECT ROW_NUMBER() OVER(ORDER BY BOOK_NO DESC) 일련번호, BOOK_NO, BOOK_TITLE

FROM SAMPLE_BOOK;

-- 많이 사용되는 방법

SELECT RN, BOOK_NO, BOOK_TITLE

FROM (SELECT ROW_NUMBER() OVER(ORDER BY BOOK_NO DESC) RN, BOOK_NO, BOOK_TITLE FROM SAMPLE_BOOK)

WHERE RN >= 1 AND RN <= 3;

 

 

-- 1. Zlotkey 동일한 부서에 속한 모든 사원의 이름과 입사일 표시.

SELECT DEPARTMENT_ID

FROM EMPLOYEES

WHERE last_name = 'Zlotkey';

 

SELECT last_name, HIRE_DATE

FROM EMPLOYEES

WHERE department_id = (SELECT DEPARTMENT_ID

                        FROM EMPLOYEES

                        WHERE last_name = 'Zlotkey');

 

-- 2. 급여가 평균 급여보다 많은 모든 사원의 사원번호와 이름을 표시.

SELECT EMPLOYEE_ID, LAST_NAME, SALARY

FROM EMPLOYEES

WHERE SALARY > (SELECT avg(SALARY)

                  FROM EMPLOYEES)

                  ORDER BY SALARY ASC;

 

-- 3. 이름에 u 포함된 사원과 같은 부서에 일하는 모든 사원의 사원번호와 이름 표시.

SELECT DEPARTMENT_ID

from EMPLOYEES

where LAST_NAME like '%u%';

 

SELECT employee_id, last_name

fROM EMPLOYEES

where DEPARTMENT_ID in (SELECT DEPARTMENT_ID

                      from EMPLOYEES

                      where LAST_NAME like '%u%');

 

 

-- 4. 부서 위치 아이디가 1800 모든 사원의 이름, 부서번호, 업무아디 표시.

SELECT DEPARTMENT_ID

FROM DEPARTMENTS

WHERE LOCATION_ID = 1800;

 

SELECT LAST_NAME, DEPARTMENT_ID, JOB_ID

FROM EMPLOYEES

where DEPARTMENT_ID in(SELECT DEPARTMENT_ID

                      FROM DEPARTMENTS

                      WHERE LOCATION_ID = 1800);

                     

SELECT E.LAST_NAME, D.DEPARTMENT_ID, E.JOB_ID

FROM EMPLOYEES E, DEPARTMENTS D

WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID

AND D.LOCATION_ID = 1800;

 

 

-- 5. King 관리하는 모든 사원의 이름과 급여 표시

SELECT EMPLOYEE_ID

FROM EMPLOYEES

WHERE LAST_NAME = 'King'

and MANAGER_ID is null;

 

 

SELECT LAST_NAME, SALARY, MANAGER_ID

FROM EMPLOYEES

WHERE MANAGER_ID in (SELECT EMPLOYEE_ID

                      FROM EMPLOYEES

                      WHERE LAST_NAME = 'King');

 

-- 6. Executive 부서의 모든 사원에 대한 이름과 업무이름 표시.

SELECT e.LAST_NAME, j.JOB_ID, J.JOB_TITLE

FROM EMPLOYEES E, JOBS J

WHERE E.JOB_ID = J.JOB_ID

and DEPARTMENT_ID in (SELECT DEPARTMENT_ID

                        FROM DEPARTMENTS

                        WHERE DEPARTMENT_NAME = 'Executive');

 

 

 

 

 

 

DML

          -insert, update, delete

 

DDL(Data definition language)

          - 오라클의 객체(테이블, , 시퀀스, 인덱스, 동의어)

          - CREATE(생성), ALTER(수정), DROP(삭제), TRUNCATE(비우기)

 

   테이블

      - 테이블 이름은, 문자 숫자 특문(_ $ #) 사용 가능

      - 문자로 시작해야함

      - CREATE TABLE 테이블명 (

          칼럼명 데이터 타입 DEFALULT 기본값.

          컬럼명  데이터 타입

          )

 

 

   오라클의 데이터 타입

     - VARCHAR2(size)     - 가변 길이 문자 데이터, 최대 4000byte

                              이름, 제목, 주소, 리뷰... 같은

 

     - CHAR(size)         - 고정 길이 문자 데이터, 최대 2000byte

                              주민번, 우편번호, 군번, 학번... 같은..

 

     - DATE               - 날짜와 시간정보 (, , , , , )

     - TIMESTAMP          - 날짜와 시간정보 (, , , , , , 소숫점 이하의 )

 

     - NUMBER(p,5)        - 숫자(p:십진자리수, s:소수점 자리수)

     - LONG               - 가변길이 문자 데이터 2GB

     - CLOB               - 가변길이 문자 데이터 4GB

     - BLOB               - 이진데이터(사진, 영상, 기타..) 4GB

 

 

   예제 테이블 만들기.

방명록 테이블

     - 작성자, 작성일자, 열람횟수, 내용

 

ALTER TABLE

     - 컬럼 추가, 컬럼 수정, 컬럼 삭제

     - 컬럼 추가

       ALTER TABLE 테이블명

       ADD (컬럼명 데이터 타입);

 

     - 컬럼 수정 < 데이터타입, 크기, 기본값 등을 변경할 있다.

       ALTER TABLE 테이블명

       MODIFY (컬럼명 데이터타입)

 

     - 컬럼 삭제

       ALTER TABLE 테이블명

       DROP COLUMN 컬럼명;

 

 

Create Table BAND_Article (

  NO          NUMBER            PRIMARY KEY

  Writer      varchar2(500)     NOT NULL,

  Write_DATE  DATE              default sysdate,

  Read_cnt    NUMBER(10)        default 0,

  contents    varchar2(4000)

)

 

 

-- 테이블 데이터 삭제       

DELETE FROM BAND_ARTICLE;

  ㄴ롤백으로 되돌리기 가능.

 

TRUNCATE TABLE BAND_ARTICLE;

  롤백으로도 불가능.

  테이블 모든 행을 제거하고, 테이블이 사용했던 저장공간을 해제.

  DELETE보다 처리 속도가 빠름.

  해당 테이블 초기화

 

 

-- 테이블 삭제

DROP TABLE BAND_ARTICLE;

 

 

 

반응형