* Oracle - 조직 tree

 

     1. 사용처 : 해양수산부

     2. 정의 : 현재 기준으로 조직tree정보를 보여준다.
                  테이블에는 조직history정보는 없고, 현재기준으로만 조직을 보여주고 있다.
                  아래 SQL 문은 조직 조회 후 계층적으로 정렬을 해서 가져온다.
                  조직tree를 가져 올때 상위조직코드를 이용해서 상위부터 하위로 가져오는 sql 문이다.

     3. 테이블 정의 : KCS_SYSORG  -> 조직정보

SELECT *
FROM  (
               SELECT sys_cd,         --평가시스템코드
                             EORGCD,
                             org_gubun,      --조직구분(1:본청,2:소속,3:산하)
                             REF_UPPER_DEPT, --상위부서코드
                             dept_name,      --부서명
                             DISP_ORDER,
                             ORG_LEVEL,      --조직레벨
                             sys_connect_by_path(ORG_LEVEL || DISP_ORDER || EORGCD, '/') EORGCD2,
                             LONG_NAME,
                             DISP_DEPTH,
                             fnc_getfinaldept(sys_cd,eorgcd) lowcount --하위부서갯수
                 FROM   KCS_SYSORG
                 WHERE  sys_cd =  ?    -- @시스템코드
                 AND       useyn   = 'Y'
                 START WITH EORGCD  = ? --@조직코드
                 CONNECT BY PRIOR EORGCD = REF_UPPER_DEPT
             )
ORDER BY EORGCD2, DISP_ORDER, ORG_LEVEL, REF_UPPER_DEPT, DISP_ORDER ;

 

'(DB) Oracle > SQL' 카테고리의 다른 글

Oracle - 조직 TREE SQL 1  (0) 2017.01.18
Oracle - SQL문에서_한글검색_방법  (0) 2017.01.18
Oracle - 예제_SUBQUERY  (0) 2017.01.18
Oracle - 예제_FOR_UPDATE_WAIT  (0) 2017.01.18
Oracle - 예제_CASE_예제1  (0) 2017.01.18
Posted by 농부지기
,

                              * Oracle - 조직 tree

 

     1. 사용처 : 중진공

     2. 내용 : 조직tree를 보여 줄 때 '기준일자'를 기준으로 조직tree를 조회할 수 있다.
                 기준일자란, 현재일자기준으로 조직을 보여주는 것이 아니고, 현재 보다 이전
                                   일자를 아무때나 지정하여 해당일자의 조직으로 tree를 보여준다.

     3. 테이블정의 : orm_org_relation  : 조직 연관관계 테이블
                            orm_organization : 해당 조직코드의 정보

 

SELECT  rel.hir_level org_level,
              org.org_nm,
              org.org_cd,
              org.virtual_cd,
              org.org_num,
              org.org_nm_eng,
              org.org_short_nm,
              org.org_full_nm,
              org.note,
              org.org_id,
              rel.up_org_id,
              rel.up_org_cd,
              rel.sta_ymd org_sta_ymd,
              rel.end_ymd org_end_ymd,
              org.com_org_cd,
              org.org_type_cd,
              rel.org_order ,
              rel.org_rank,
              org.location_cd,
              org.biz_cd,
              rel.org_line

FROM (SELECT LEVEL AS hir_level
                        ,a.sta_ymd, a.end_ymd
                        ,SYS_CONNECT_BY_PATH( TO_CHAR(a.org_rank, '000') || ':' ||a.org_id,  '/') org_order
                        ,a.org_id,a.up_org_id, a.org_rank, a.up_org_cd, a.org_line
           FROM  orm_org_relation a
           START WITH a.org_id = ?
                      AND  ?  BETWEEN a.sta_ymd AND a.end_ymd
           CONNECT BY PRIOR a.org_cd = a.up_org_cd
                          AND ? BETWEEN a.sta_ymd AND a.end_ymd
           ORDER SIBLINGS BY a.org_rank  
          ) rel

        , orm_organization org

 WHERE org.org_id = rel.org_id  ;

 

'(DB) Oracle > SQL' 카테고리의 다른 글

Oracle - 조직 TREE SQL 2  (0) 2017.01.18
Oracle - SQL문에서_한글검색_방법  (0) 2017.01.18
Oracle - 예제_SUBQUERY  (0) 2017.01.18
Oracle - 예제_FOR_UPDATE_WAIT  (0) 2017.01.18
Oracle - 예제_CASE_예제1  (0) 2017.01.18
Posted by 농부지기
,

Oracle - SQL문에서 한글검색  방법 1

 

 

1. 요구사항 : between 'ㄱ' and  'ㄴ'   까지 검색 (첫글자가  ㄱ ~ ㄴ)

2. SQL문      : ASCII (substr(:STRING, 1, 2) BETWEEN  45217 AND  51454

3. 참고         : ㄱ 이 들어간 문자열을 조회하시려면 KSC5601 code테이블을 참조하면 된다.

                 WHERE 컬럼 >= '가'

                 AND     컬럼 < '나'

 

'(DB) Oracle > SQL' 카테고리의 다른 글

Oracle - 조직 TREE SQL 2  (0) 2017.01.18
Oracle - 조직 TREE SQL 1  (0) 2017.01.18
Oracle - 예제_SUBQUERY  (0) 2017.01.18
Oracle - 예제_FOR_UPDATE_WAIT  (0) 2017.01.18
Oracle - 예제_CASE_예제1  (0) 2017.01.18
Posted by 농부지기
,

Oracle - SUBQUERY

 

1. 1999의 스칼라 서브 쿼리 정의

2. SELECT 리스트에서의 서브 쿼리

3. WHERE 절에서의 스칼라 서브 쿼리

4. ORDER BY 절에서의 스칼라 서브 쿼리

5. CASE 수식에서의 스칼라 서브 쿼리

6. 함수에서의 스칼라 서브 쿼리

 

 

1999의 스칼라 서브 쿼리 정의

정의)

- 스칼라 서브 쿼리는 쿼리 수식으로부터 유도된 스칼라 값을 지정하기 위해 사용됩니다.

- Oracle8i 에서는 다음과 같이 제한된 경우에만 지원이 되었습니다.

    .  삽입 문장의 VALUES 리스트

    .   데이터 형 생성자에 대한 인자

- Oracle9i에서 스칼라 서브 쿼리는 유효한 수식이 쓰일 수 있는 모든 곳에서 사용될 수 있습니다.

- 스칼라 서브 쿼리는 오직 하나의 값만 반환합니다.

- 반환되는 값의 데이터 형은 서브 쿼리에서 선택되는 데이터 형과 일치합니다.

 

사용)

- GROUP BY를 제외한 모든 SELECT 절

- INSERT 문의 VALUES 절

- UPDATE 문의 SET 절 및 WHERE 절

- DECODE 및 CASE의 조건 내지 수식

 

예) SELECT 리스트에서의 서브 쿼리

SELECT employee_id, last_name, (

           SELECT department_name

         FROM departments d

  WHERE e.department_id = d.department_id

 ) department_name

  FROM employees e

ORDER BY department;

 

 

예) WHERE 절에서의 스칼라 서브 쿼리

 

SELECT employee_id, last_name

  FROM employees e

 WHERE ((SELECT location_id

                  FROM departments d

                 WHERE e.department_id = d.department_id)                      =

        (SELECT location_id

           FROM locations l

                 WHERE STATE_province = 'California')

        );

 

예) ORDER BY 절에서의 스칼라 서브 쿼리

 

SELECT employee_id, last_name

      FROM employees e

    ORDER BY (

  SELECT department_name

        FROM departments d

       WHERE e.department_id = d.department_id

);

 

예) CASE 수식에서의 스칼라 서브 쿼리

 

 SELECT employee_id, last_name,

       (CASE

              WHEN department_id IN

                    (SELECT department_id FROM departments

                      WHERE location_id = 1800)

                 THEN 'Canada' ELSE 'other'

        END) location

   FROM employees;

 

예) 함수에서의 스칼라 서브 쿼리

 

SELECT last_name, SUBSTR (

           (SELECT department_name

                  FROM departments d

                 WHERE d.department_id = e.department_id),

                1, 10) department

  FROM employees e;

   

 

 

'(DB) Oracle > SQL' 카테고리의 다른 글

Oracle - 조직 TREE SQL 1  (0) 2017.01.18
Oracle - SQL문에서_한글검색_방법  (0) 2017.01.18
Oracle - 예제_FOR_UPDATE_WAIT  (0) 2017.01.18
Oracle - 예제_CASE_예제1  (0) 2017.01.18
Oracle - 예제_JOIN  (0) 2017.01.18
Posted by 농부지기
,

Oracle - FOR UPDATE WAIT

 

정의)

    - 이전 릴리즈의 Oracle에서 SELECT... FOR UPDATE 문장을 수행할 때 읽을 행들에 락이 걸려 있다면,

       락이 해제되길 기다리던지 아니면 바로 에러를 반환하도록 하는 두 가지 옵션만이 가능했습니다

    - Oracle9i에서는 SELECT... FOR UPDATE 문장이 WAIT 키워드를 이용하여 락이 해제되길 기다리는 시간을 명시할 수 있도록 수정되었습니다.

    - 바로 에러를 반환하도록 하는 것은 NOWAIT 을 지정함으로써 가능합니다.

이점)

    - 락이 걸린 행들을 무한정 기다리게 되는 현상을 방지할 수 있습니다.

    - 락에 대한 대기 시간을 지정할 수 있도록 하는 것은 특히 대화형의 애플리케이션 개발에 유익합니다.

 

예)

    SELECT *

    FROM EMPLOYEES

    WHERE DEPARTMENT_ID = 10

    FOR UPDATE WAIT 20;

 

 

'(DB) Oracle > SQL' 카테고리의 다른 글

Oracle - SQL문에서_한글검색_방법  (0) 2017.01.18
Oracle - 예제_SUBQUERY  (0) 2017.01.18
Oracle - 예제_CASE_예제1  (0) 2017.01.18
Oracle - 예제_JOIN  (0) 2017.01.18
Oracle - 예제_LEAD.LAG  (0) 2017.01.18
Posted by 농부지기
,

Oracle - CASE 문

 

- SQL:1999에는 다음과 같은 형태의 CASE 문들이 있습니다.

   . 단순 CASE

   . 검색 CASE

   . NULLIF

   . COALESCE

 

1) 단순 CASE 수식

    - 단순 CASE 수식은 DECODE 함수와 유사합니다.

    - 주어진 수식 내에서 값을 찾고 대체할 수 있습니다.

    - 각각의 값에 대해 반환값을 명시할 수 있습니다.

    - 비교 연산자를 사용할 수는 없습니다.

    - 예)

        SELECT last_name,

                     (CASE department_id

                      WHEN 10 THEN 'Administration'    

                      WHEN 20 THEN 'Marketing'         

                      WHEN 30 THEN 'Purchasing'        

                      WHEN 40 THEN 'Human Resources'   

                      …

                      ELSE 'N/A'

                       END) as "Department Names"

        FROM employees

        ORDER by department_id;

 

2) 검색 CASE 수식

    - 검색 CASE 수식은 IF… THEN … ELSE 구문과 유사합니다.

    - 수식에 대하여 조건부로 값을 찾고 대체할 수 있습니다.

    - 각각의 WHEN 조건은 달리 주어지며 복수의 조건이 논리 연산자에 의해 결합될 수 있습니다.

    - 조건 수식에 비교 연산자를 사용할 수 있습니다.

    - 검색 CASE 수식은 단순 CASE 수식에 비해 보다 유연합니다.

    - 예)

          SELECT last_name,

                 CASE

                   WHEN job_id LIKE 'AD%' THEN '10%'

                   WHEN job_id LIKE 'IT%' THEN '15%'

                   WHEN job_id LIKE 'PU%' THEN '18%'

                   ELSE '20%'

                 END

            FROM employees;

 

 

'(DB) Oracle > SQL' 카테고리의 다른 글

Oracle - 예제_SUBQUERY  (0) 2017.01.18
Oracle - 예제_FOR_UPDATE_WAIT  (0) 2017.01.18
Oracle - 예제_JOIN  (0) 2017.01.18
Oracle - 예제_LEAD.LAG  (0) 2017.01.18
Oracle - 예제_UPDATE  (0) 2017.01.18
Posted by 농부지기
,

                                   [ JOIN ]

☞ JOIN 기본개념 및 종류

 

- 정의 :  하나 이상의 테이블로부터 연관된 데이터를 검색해오는 방법
- Join의 종류
   1. Equijoin       : 컬럼간의 값들이 서로 정확히 일치하는 경우에 사용, 일반적으로 PK,
                       FK 관계에 의함
   2. Non-Equijoin   : 한 컬럼의 값이 다른 컬럼의 값과 정확히 일치하지 않는 경우에 사용
   3. Outer Join     : Join 조건을 만족하지 않는 경우에도 모든 행들을 다 보고자 하는  경우 사용
   4. Self Join      : 같은 테이블에 있는 행들을 Join하고자 하는 경우에 사용
   5. Cartesian Join : Join에 대한 조건이 생략되거나 잘못 기술되면 한 테이블에 있는 모든
                       행들이 다른 테이블에 있는 모든 행들과 Join이 되어 얻어진 결과
   6. ANSI Join
     ㅇ Natural Join : 두 테이블에 공통 칼럼이 있는 경우 별다른 조인 조건 없이 공통 칼럼에
                       대해 묵시적으로 조인이 되는 유형
     ㅇ JOIN ~ USING : 조인하고자 하는 테이블에 같은 이름의 칼럼이 많은데, 이 중 특정한
                       칼럼으로만 조인하고 싶다면 조인하고자 하는 칼럼명에 USING 절을 사용
   7. CROSS JOIN    : CROSS 죠인은 두 테이블의 곱집합을 생성한다.
                      이는 두 테이블 간의 Cartesian 곱과 같다. 
   8. FULL OUTER 조인
   9. INNER JOIN    : SQL: 1999 표준에 의하면 두 테이블을 죠인하여 오로지 대응되는 행들만을
                      반환하는 것을 INNER 죠인이라 합니다.
                      INNER 죠인의 결과와 함께 왼쪽(오른쪽) 테이블의 대응되지 않는 행들도
                      반환하는 것을 LEFT(RIGHT)OUTER 죠인이라 합니다.
                      INNER 죠인의 결과와 함께 LEFT 및  RIGHT OUTER 죠인의 결과까지 모두
                      반환하는 것을 FULL OUTER 죠인이라 합니다.
   10. NATURAL JOIN : 
         NATURAL 죠인은 두 테이블에서 같은 이름을 가진 모든 컬럼에 기반한다.
         두 테이블의 대응되는 모든 컬럼에 대해 같은 값을 가지는 행들을 선택한다.
         만일 같은 이름을 가지는 컬럼들이 서로 다른 데이터 형을 가질 때에는 오류가 반환된다.
         만일 SELECT * 문법을 사용한다면, 공통 컬럼들은 결과 집합에서 단 한번만 나타난다.
         테이블 이름이나 가명 등의 수식자들은 NATURAL 죠인에 사용된 컬럼들을 수식할 수 없다. 

☞ 


☞ ANSI Join

 

예시) SELECT d.name, r.name
      
FROM   s_dept d
      
JOIN   s_region r USING (region_id)
      
WHERE  r.name like '%서울%' ;
     ㅇ JOIN ~ ON : 공통된 이름의 칼럼이 없다거나, 일반적인 조인을 수행하는 경우 가장
                    보편적으로 사용되는 조인 유형

예시)
SELECT e.name 사원명,  d.name  부서명, r.name  지역명
      
FROM   s_emp e
      
JOIN   s_dept d   ON (e.dept_id   = d.dept_id )
      
JOIN   s_region r ON (d.region_id = r.region_id )
      
WHERE  d.name = '인사부' ;

USING절을 이용한 조인
   만일 여러 개의 컬럼이 이름은 같지만 데이터 형이 모두 일치되지는 않을 때에는, NATURAL JOIN은    USING 절을 이용하여 동등 죠인에 사용될 컬럼들을 명시하도록 수정될 수 있습니다.

   USING 절에서 참조되는 컬럼들은 SQL 문 어디에서도 수식자(테이블 이름이나 가명)에 의해
   수식될 수 없습니다.

   NATURAL 과 USING의 두 키워드는 상호 배타적으로 사용됩니다.

예시) SELECT e.employee_id, e.last_name, d.location_id
      FROM   employees e JOIN departments d  USING (department_id);

 

 

 

☞ SELF Join

 

정의  : 한 테이블의 행을 같은 테이블에 있는 행과 연결하는 방법으로 같은 테이블을 마치 두 개의
        테이블인 것처럼 사용하여 Join하는 방법
예시1) SELECT  w.id 사번, w.name 사원명, m.id 부서장사번, m.name 부서장명
          FROM s_emp w, s_emp m
          WHERE  w.manager_id = m.id ;
   예시2) SELECT  w.id 사번, w.name 사원명, m.id 부서장사번, m.name 부서장명
          FROM s_emp w JOIN s_emp m
          ON  w.manager_id = m.id  ;

☞ Non-equ Join

 

정의 : 한 칼럼의 값이 다른 칼럼의 값과 정확히 일치하지 않는 경우에 연산자 외의 다른 연산자를
       사용하여 Join하는 방법
예시1)
SELECT e.name, e.salary , g.grade 급여등급
      
FROM   s_emp e, salgrade g
      
WHERE  e.salary BETWEEN g.losal AND g.hisal ;
예시2)
SELECT
e.name, e.salary , g.grade 급여등급
      
FROM   s_emp e JOIN  salgrade g ON  e.salary BETWEEN g.losal AND g.hisal ;

☞ Outer Join

 

예시) SELECT  e.name 사원명,e.id,c.name 고객명
      
FROM    s_emp e, s_customer c
      
WHERE   e.id(+) = c.sales_rep_id OR RIGHT JOIN s_customer c ON  e.id = c.sales_rep_id
      
ORDER BY
2;

 

- UNION(합집합), UNION ALL(합집합+교집합), INTERSECT(교집합), MINUS(차집합)
※ 첫 번째 SELECT구문에서 기술된 칼럼들과 두 번째 SELECT구문에서 기술된 칼럼들은 그 개수와
   타입이 일치해야 함.
※ 칼럼의 Heading은 첫번째 SELECT구문의 칼럼명이 출력됨
※ ORDER BY절은 마지막에 한 번만 기술됨

예시) S_EMP 테이블에서 사원의 사번, 이름, 그리고 담당 부서장을 아래의 결과와 같이 출력하되,
      Outer Join을 사용하지 않고 SET연산자를 사용하여 담당부서장이 없는 사원까지 나타내시오.

SQL>
SELECT  w.id 사번, w.name 사원명 , m.name 부서장명
     
FROM    s_emp w, s_emp m
     
WHERE   w.manager_id = m.id  
     
UNION
     
SELECT  id 사번, name 사원명 , '부서장없음'
     
FROM    s_emp
     
WHERE   manager_id is null ;

Outer Join 연산의 경우)
SQL>
SELECT  w.id 사번, w.name 사원명 , m.name 부서장명
     
FROM    s_emp w LEFT JOIN s_emp m ON
m.id = w.manager_id ;

 

▣ LEFT OUTER 조인
   SELECT e.last_name, d.department_name
   
FROM   employees e LEFT OUTER JOIN departments d
          
ON
(e.department_id = d.department_id);

 

RIGHT OUTER 조인
   
SELECT e.last_name, d.department_name
   
FROM   employees e RIGHT OUTER JOIN departments d
             
ON(e.department_id = d.department_id)

 


☞ CROSS Join

 

SELECT last_name, department_name
FROM   employees CROSS JOIN
departments;

 


☞ NATURAL JOIN

 

SELECT department_id, location_id
FROM   locations NATURAL JOIN departments;

 


☞ FULL OUTER JOIN

 

 SELECT e.last_name, d.department_name
 
FROM   employees e FULL OUTER JOIN departments d ON (e.dept_id = d.dept_id);

 


☞ 추가JOIN방법  

 

▣ Exists를 이용한 조회

      FROM locations l JOIN departments d  
           ON
((l.location_id = d.location_id) AND NOT EXISTS ( SELECT 1 FROM employees e
                                                                
WHERE e.dept_id = d.dept_id
                                                              )
               );

 

 


 

'(DB) Oracle > SQL' 카테고리의 다른 글

Oracle - 예제_FOR_UPDATE_WAIT  (0) 2017.01.18
Oracle - 예제_CASE_예제1  (0) 2017.01.18
Oracle - 예제_LEAD.LAG  (0) 2017.01.18
Oracle - 예제_UPDATE  (0) 2017.01.18
Oracle - 예제_SUBQUERY  (0) 2017.01.18
Posted by 농부지기
,

[Oracle - 예제_LEAD.LAG]

 

 

[CHAPTER 1] 자료의 조회     

 

  

☞ Guidelines

 

  commit 과 rollback 과의 차이점

 

  commit은 저장이고 rollback은 취소다.

 

  취소는 바로 직전까지 commit된 이후의 작업에 대한 취소이다

 

  하나의 트랜잭션이 완료된다는 것은 commit까지를 의미한다

 

  commit를 하지 않아도 commit되는 경우는 다음과 같다

 

  ① DDL 이나 DCL 문장을 만났을 때

 

  ② SQL*PLUS 에서 EXIT이용하여 정상 종료되었을 때

 

  ③ SET autocommit on 으로 환경이 설정되어 있을때

 

  예를 들면

 

  create table test as select ykiho from tbjcc10 where rownum < 10;   

 

● null 의 이해

 

 정의: null 은 column 에 값이 아무것도 없다는 의미

 

 질의: where 문에서는 반드시

 

       where a is null  혹은  where a is not  null 를 사용해야 한다

 

       만약 아래와 같이 사용시 예상치 않는 결과가 초래할 수 있다

 

       where a = null  혹은 where a <> null

 

 NVL사용:select emp_name, nvl(hobby,'없음') from temp;

 

            즉 hobby 가 null 인 사람은 모두 hobby를 '없음'이라고 표시하라는 의미임

 

 

 

● alias를 반드시 사용할 경우

 

  ■ table alias 사용시

 

     self join 일 경우에는 반드시 table alias를 사용해야 한다

 

     ※ self join 이란  

 

         때때로 자체적으로 테이블을 조인할 필요가 있다.

 

         각 종업원의 관리자 명을 알기 위해서 자체적으로 EMP 테이블을 조인하는 것이

 

         필요함.

 

     ☞ Guidelines

 

     1) Self join을 사용하여 한 테이블의 행들을 같은 테이블의 행들과 조인한다.

 

     2) 같은 테이블에 대해 두 개의 alias를 작성(테이블 구분)함으로 FROM절에 두 개의

 

        테이블을 사용하는 것과 같이 한다.

 

     3) Column에 대해서도 어떤 테이블에서 왔는지 반드시 Alias명을 기술하여야 한다.

 

     4) 테이블 하나를 두개 또는 그 이상으로 Self join할 수 있다.

 

     

 

     예시) EMP 테이블에서 Self join하여 관리자를 출력시

 

     

 

     SQL> SELECT worker.ename || '의 관리자는 ' || manager.ename || '이다'

 

     2  FROM emp worker, emp manager

 

     3  WHERE worker.mgr = manager.empno;

 

     WORKER.ENAME||'의관리자는'||MANAGER.

 

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

 

     BLAKE의 관리자는 KING이다

 

     CLARK의 관리자는 KING이다

 

     13 rows selected.

 

 

 

  ■ column  alias 사용시

 

     rownum 을 사용할 경우 즉 inline view안에서 사용되어 진 후 다시 이들을 from 절로

 

     사용하는 query에서 rownum 이용시 반드시 column alias 를 사용해야 한다.      

 

 

 

     예시) 요양기호중 3번째로 큰 요양기호를 추출하는 SQL 문장 작성하기.

 

     select YKIHO

 

     from ( select /*+ index_desc(TBJCC10  PK_TBJCC10) */ rownum num, YKIHO

 

     from TBJCC10  where YKIHO  > 0 and rownum < 4)

 

     where num = 3;

 

 

 

● 합성연산자 사용시 (concatenation )

 

   두개 이상의 문자열을 연결하여 하나의 문자열을 만들어낼 때 ( || )

 

    set heading off

 

    set feedback off

 

    set pause off

 

    spool s_drop_all.sql

 

    select 'drop table  '|| table_name|| ' cascade constraints;' from user_tables;

 

    spool off

 

    위의 합성연산자로 만든 자료는 pc excel file로 활용을 많이 하고 있음

 

         

 

● where 절 사용시 기본사항

 

   오라클의 rule base optimizer mode에서 index이용시 where절을 이용하여

 

   index를 사용하거나 유도할 수 있다

 

   ① select ykiho from tbjcc10; // 입력순서대로 display

 

   ② select ykiho from tbjcc10 where ykiho > 0; // ykiho 가 pk_ykiho 존재. ykiho 순서적 display

 

     ③ select max(ykiho) from tbjcc10; // full table scan 한후 max 값을 reutrn 한다

 

     ④ select /*+ index_desc(TBJCC10  PK_TBJCC10) */ YKIHO // index search 내림순중

 

                                                             1번째를 return

 

      from  TBJCC10  

 

      where YKIHO > 0 and rownum = 1;

 

 ■ optimizer mode와 실행계획

 

    optimizer는 수행하고자 하는 DML(select,delete,update,insert)을 가장 효율적으로

 

    처리할 수 있는 최적의 경로를 찾아 주는 것이 주임무다

 

    이러기 위해 필요한 내부요인을 보면

 

    ① 어떤table를 먼저 읽을 것인가

 

    ② table읽을시 index사용할 것인가

 

    ③ index사용시 어떤 index를 사용할 것인가

 

    ④ join 시 어떤 방법 join할 것인가(동등join,outer join, self join )

 

    위와 같은 실행계획에 의거 수핼경로는 PLAN을 통해서 알 수 있다

 

    

 

    ▶ PLAN 정보 확인 방법

 

       구성: PLAN TABLE를 만들어야 한다

 

        예시: sqlplus hira_insp/hira_insp

 

                        SQL>@ORACLE_HOME/rdbms/admin/utlxplan.sql 를 실행하여 plan_table생성 후

 

              public synonym 을 만든다

 

              SQL> create public synonym plan_table for sys.plan_table;

 

 

 

 ● INDEX를 조회할 수 있는 DATA DICTIONARY

 

    INDEX를 조회할 수 있는 DATA DICTIONARY를 보면

 

   ① USER_INDEXES

 

           TABLE이 소유하고 있는 INDEX가 어떤 것인지 알아볼 수 있다

 

       SQL> select table_name,index_name,uniqueness

 

                      from user_indexes

 

                      where table_name  = 'TBJFC02';

 

   ② USER_IND_COLUMNS  

 

           INDEX가 어떤 COLUMN으로 구성되어 있는가를 확인할 수 있다

 

           SQL>select table_name,index_name,column_position,column_name

 

                    from user_ind_columns

 

                    where table_name = 'TBJCC10'

 

                    order by table_name,index_name,column_position

 

 

 

● PCTFREE 와 PCTUSED

 

   ① PCTFREE 10  (defalut)

 

          이미 블럭에 쓰여진 UPDATE,INSERT를 위하여 예역되는 공간을 말한다

 

      PCTFREE 10 즉 블럭의 공간중 10%를 이미 블록에 쓰여진 ROW의 UODATE나

 

      INSERT를 위하여 사용되지 않고 남게 하겠다는 의미임  

 

   ② PCTUSED 40  (defalut)            

 

      PCTFREE에서 지정한 영역만큼만 FREE SPACE가 남게 되면 오라클은 더 이상

 

      해당 블록에 새로운 ROW를 삽입할 수 없다

 

      사용공간이 ROW의 삭제등으로 인하여 PCTUSED에서 지정한 값 아래로 떨어지게

 

      되면 그때 다시 해당 BLOCK에 새로운 ROW가 삽입될 수 있다

 

 

 

● 연산자

 

    총6자리 부서코드중 2번째 자리에 A 가 들어가는 ROW를 검색  

 

    SQL>select emp_id, emp_name, dept_code

 

                from temp

 

                where  dept_code like '_A____';

 

 

 

[CHAPTER 2] 함수     

 

 

 

● SUBSTR

 

      SQL>select substr(ykiho,3,1),count(*)

 

                from  tbjcc10

 

                group by substr(ykiho,3,1)

 

 

 

    ■ SUBSTR와 SUBSTRB 차이점 확인

 

     SQL> select SUBSTR(ADDR,3,10)

 

               from tbjcc10

 

               WHERE ROWNUM < 10

 

   SQL> select SUBSTRB(ADDR,3,10)

 

               from tbjcc10

 

               WHERE ROWNUM < 10

 

 

 

● CHR

 

      CHR를 이용해 개행문자의 ASCII 코드를 찾고 그 결과를 확인한다

 

 

 

  SQL> select YKIHO||CHR(10)||SUBSTR(YOYANG_NM,1,10)||CHR(10)||SUBSTR(ADDR,1,20)

 

            from tbjcc10

 

            WHERE ROWNUM < 2

 

 

 

            YKIHO||CHR(10)||SUBSTR(YOYANG_NM,1,10)||CHR(10)||SUBSTR(ADDR,1,20)

 

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

 

            11100010

 

       국립의료원

 

       서울 중구 을지로6가 18-79 국립

 

 

 

● 숫자함수(ROUND)

 

      반올림에 사용하는 함수로 양수면 소수점 아래를 의미하며, 음수면 소수점 위를 의미,

 

   생략하면 반올림해서 정수를 만든다

 

 

 

      SQL> select ROUND('1234.567',1),

 

                         ROUND('1234.567',-1),

 

                         ROUND('1234.567')

 

               from dual;

 

               1234.6............1230............1235

 

● 숫자함수(TRUNC)

 

      버림에 사용하는 함수

 

      SQL> select TRUNC('1234.567',1),

 

                         TRUNC('1234.567',-1),

 

                         TRUNC('1234.567')

 

               from dual;

 

               1234.5............1230............1234

 

 

 

● 숫자함수(MOD)

 

      주어진 숫자를 지정된 숫자로 나머지를 돌려준다

 

      SQL> select MOD(1,3),MOD(2,3),MOD(3,3),MOD(4,3)

 

               from dual;

 

               1 .........2..........0........1

 

 

 

● 날짜처리함수

 

  ■ 날짜와 숫자의 계산

 

    ① 날짜와 날짜의 덧셈과 뺄셈

 

      select ykiho,proc_dtime + sysdate

 

      from   tbjcc10 where rownum < 10;

 

       ORA-00975: 날짜와 날짜의 가산은 할 수 없습니다

 

       select ykiho,sysdate - proc_dtime  

 

      from   tbjcc10 where rownum < 10; (뺄셈은 가능)

 

    ② 날짜와 숫자의 덧셈과 뺄셈

 

       모두 가능함

 

    ③ date 형에서 시간 더하고 빼기           

 

       select

 

       ykiho,

 

       proc_dtime,

 

       to_char(proc_dtime,'hh24:mi:ss') as proc_time,

 

       to_char(proc_dtime + 14/24,'hh24:mi:ss') as time,

 

       to_char(proc_dtime + 30/(24*60),'hh24:mi:ss') as min,

 

       to_char(proc_dtime + 50/(24*60*60),'hh24:mi:ss') as sec

 

       from tbjcc10 where rownum < 2

 

    ④ ADD_MONTHS,MONTHS_BETWEEN,LAST_DAY 사용 예시

 

       select

 

       ykiho,

 

       to_char(proc_dtime,'yyyy/mm/dd')as 처리년월일,

 

       to_char(add_months(proc_dtime,1),'yyyy/mm/dd') as proc_time_1개월,

 

       to_char(add_months(proc_dtime,-13),'yyyy/mm/dd') as proc_time_13개월,

 

       round(months_between(sysdate,proc_dtime))as month_월간격,

 

       to_char(last_day(proc_dtime),'yyyy/mm/dd') as month_마지막일자,

 

       SYSDATE - TO_DATE('20000101','YYYYMMDD')

 

       from   tbjcc10 where rownum < 2

 

 

 

 

 

● 그룹함수

 

  ■ COUNT,AVG,MIN,MAX,SUM

 

    ① select count( distinct recv_dt) from tbjfc00 where recv_dt > '20020100'  

 

      ② 평균을 구할 때 null 은 포함시키면 안된다

 

       왜냐하면 salary 가 0 일 경우와 null 일 경우 평균값이 서로 상이함

 

       평균 = sum / count 에서 null 은 count에서 제외되기 때문이다

 

 

 

 

 

[CHAPTER 3] 사례 이해를 위한 기본사항     

 

 

 

● union 과 union all 의 차이점

 

    ■ union      -> 합집합을 보여주며 중복된 row 가 있을 경우 하나의 row만 포함

 

              즉 DB 내부적으로는 SORT를 한다는 의미임   

 

    ■ union all  -> 합집합을 보여주며 중복된 row 가 있을 경우 모두 보여준다

 

              즉 DB 내부적으로는 SORT를 하지 않는다는 의미임   

 

    ■ minus      -> 차집합을 구한다(sort함)

 

    ■ intersect  -> 교집합을 구한다(sort함)  

 

 

 

 ☞ Guidelines

 

    두 문장간의 자료 유형이 일치해야 하고,

 

   두 문장간의 컬럼 수가 일치해야 한다.

 

 

 

● join 의 종류를 나열하면

 

1. Join

 

하나 이상의 테이블로부터 자료를 검색하기 위하여 조인을 사용합니다.

 

일반적으로Primary Key(이후 PK로 사용)와 Foreign Key(이후 FK로 사용)을 사용하여

 

Join하는 경우가 대부분이지만 때로는 논리적인 값들의 연관으로 Join하는 경우도 있습니다.

 

1.1 Syntax

 

 

☞ Guidelines

 

1)  WHERE 절에 조인 조건을 기술한다.

 

2)  테이블을 조인하는 SELECT 문장을 작성할 경우 명확성을 위하여 또는 데이터베이스의

 

     Performance 향상을 위하여 열 이름 앞에 테이블 명을 붙인다.

 

3)  똑 같은 열 이름이 존재하는 테이블이 있을 경우는 반드시 열 이름 앞에 테이블 명을 붙인다.

 

4)  n개의 테이블을 조인 하려면 최소한 n-1번의 조인 조건 문이 필요하다.

 

1.2 Join의 종류

 

  

1.3 Cartesian Product

 

     모든 가능한 행들의 Join으로 다음과 같은 경우에 발생한다.

 

     1)  조인 조건이 생략된 경우

 

     2)  조인 조건이 잘못된 경우

 

     3)  첫번째 테이블의 모든 행이 두번째 테이블의 모든 행과 두번째 테이블의 모든 행이

 

          첫번째 테이블의 모든 행과 조인되는 경우.

 

     4)  양쪽 ROW의 개수를 곱한 결과

 

 

 

♣ 참고

 

Cartesian Product는 만은 수의 행을 생성하는 경향이 있고 결과도 거의 유용하지 못하다.

 

그러므로 모든 테이블로부터 모든 행을 조합할 필요가 없을 경우 WHERE절에 조인 조건을

 

명확히 기술하여야 한다.

 

 

 

문제1) EMP 테이블과 DEPT 테이블을 Cartesian Product하여 사원번호,이름,업무,부서번호,

 

          부서명,근무지를 출력하여라.

 

     SQL> SELECt empno,ename,job,dept.deptno,dname,loc

 

           2  FROM dept,emp

 

           3  ORDER BY empno;

 

 

 

1.4 Equijoin

 

Equijoin 이란 조인 조건에서 “=”을 사용하여 값들이 정확하게 일치하는 경우에 사용하는

 

조인을 말합니다. 대부분 PK와 FK의 관계를 이용하여 조인 합니다.

 

Equijoin은 다른 말로 단순 조인 또는 내부 조인 이라고도 합니다.

 

1.4.1) Syntax

 

 

문제2) EMP 테이블에서 사원번호,이름,업무,EMP 테이블의 부서번호,DEPT 테이블의 부서번호,

 

          부서명,근무지를 출력하여라

 

   SQL> SELECT empno,ename,job,emp.deptno,dept.deptno,dname,loc

 

         2  FROM dept,emp

 

         3  WHERE dept.deptno = emp.deptno

 

         4  ORDER BY dept.deptno;

 

 

 

1.4.2) Table에 Alias사용

 

   1)    테이블 별칭을 사용하여 긴 테이블 명을 간단하게 사용한다.

 

   2)    테이블 이름 대신에 Alias를 사용한다.

 

   3)    SQL 코드를 적게 사용하여 코딩 시간이 절약되고 메모리를 보다 적게 사용한다

 

  SQL> SELECT e.empno,e.ename,e.job,e.deptno,

 

       2  d.deptno,d.dname,d.loc

 

       3  FROM dept d,emp e

 

       4  WHERE d.deptno = e.deptno

 

       5  ORDER BY d.deptno;

 

 

 

 ☞ Guidelines

 

   1)  테이블 Alias는 30자까지 사용 가능하지만 짧을수록 더 좋다.

 

   2)  FROM절에서 Alias가 사용되면 SELECT문 전체에서 사용 가능하다.

 

   3)  테이블의 Alias에 가급적 의미를 부여

 

   4)  테이블은 현재 SELECT문장에서만 유용

 

 

 

1.5 Non-Equijoin

 

EMP와 SALGRADE 사이의 관련성은 EMP 테이블의 어떠한 column도 직접적으로 SALGRADE 테이블의

 

한 column에 상응하지 않기 때문에 Non-Equijoin이다.

 

두 테이블 사이의 관련성은 EMP 테이블의 SAL열이 SALGRADE 테이블의 LOSAL과 HISAL열 사이에

 

있다는 것이다. 조인 조건은 등등(=) 이외의 연산자(BETWEEN ~ AND ~)를 갖는다.

 

 

문제3) EMP 테이블에서 사원번호,이름,업무,급여,급여의 등급,하한값,상한값을 출력하여라.

 

 

♣ 참고

 

위 질의가 실행될 때 한번만 조인되는 것을 알 수 있다. 이에 대한 두가지 이유가 있다.

 

1)  SALGRADE 테이블에서 중복되는 등급을 포함하는 행이 없다.

 

2)  EMP 테이블에 있는 SAL의 값은 SALGRADE 테이블에서 제공하는 값 범위에 있다.

 

 

 

☞ Guidelines

 

<= 및 >= 같은 다른 연산자를 사용 가능하나 BETWEEN이 가장 단순하다.

 

또한 테이블에 Alias를 사용하였는데 이는 모호성 때문이 아니라 성능 때문에 사용하였다.

 

BETWEEN 사용시 하한값을 먼저 명시하고 상한값을 나중에 명시한다는 것을 명심하라.

 

 

 

1.6 Outer Join

 

행이 조인 조건을 만족하지 않으면, 행은 질의 결과에 나타나지 않을 것입니다.

 

예를 들어  EMP와DEPT테이블의 equijoin조건에서 부서OPERATIONS(40번 부서)는

 

해당 부서에 아무도 없기 때문에 나타나지 않습니다. 이런 경우 모든 행을 전부 출력하고자

 

할 경우 Outer Join을 사용한다. 즉 정상적으로 조인 조건을 만족하지 못하는 행들을 보기

 

위해 Outer join을 사용한다.

 

 

☞ Guidelines

 

   1)  행인 조건을 만족하지 않을 시 해당 행은 질의 결과에 나타나지 않는다.

 

   2)  Outer join 연산자를 조인 조건에 사용시 조인 조건을 만족하지 않는 행들도 결과에

 

        나타날 수 있다.

 

   3)  연산자는 괄호로 묶인 플러스 기호(+)이며 조인 시킬 값이 없는 조인 측에 "(+)"를

 

        위치 시킨다.

 

   4)  (+)연산자는 한 개 이상의 NULL 행을 생성하고 정보가 충분한 테이블의 한 개 이상의

 

        행들이 이런 NULL 행에 조인된다.

 

   5)  Outer join 연산자는 표현식의 한 편에만 올 수 있다.

 

   6)  Outer join을 포함하는 조건은IN 연산자, OR 연산자를  사용하여 다른 하나의 조건에

 

        연결될 수 없다.

 

1.6.1) Syntax

 

 

table1.column          테이블을 함께 조인(또는 관련)시키는 조건입니다.

 

table2.column(+)      (+)는 outer join기호입니다. WHERE절 조건의 양쪽이 아니라

 

                                어느 한쪽에 둘 수 있습니다. 즉 양측 모두에는 올 수 없습니다.

 

                                일치하는 행이 없는 테이블의 열 이름 뒤에 outer join연산자

 

                                를 사용합니다.

 

1.6.2) Outer Join제약 사항

 

   1)   Outer Join연산자는 정보가 부재하는 쪽의 표현식 한 쪽에만 둡니다. 다른 테이블의

 

         어떠한 열과도 직접적으로 일치하는 것이 없는 한 테이블의 행을 리턴합니다.

 

   2)   Outer Join을 포함하는 조건은 IN연산자를 사용할 수 없고, OR연산자에 의해

 

         다른 조건과 연결될 수 없습니다.

 

 

 

[보충설명]

 

두개 이상의 table join시 한쪽의 table의 행에 대해 다른쪽 table에 일치하는 행이 없더라도

 

다른 쪽 table의 행을 null 로 하여 행을 return하는 것이 outer join이다.

 

 

 

from  dept d , emp e

 

where d.deptno = e.deptno(+)  으로 예시를 들면  

 

 

 

이 경우 기준이 되는 table은 dept 다. 물론 양쪽 모두에 존재하는 값은 모두 나온다.

 

단, dept 에는 없고 emp 에 존재하는 값이 있는 경우에는 return 되지 않는다.

 

 

 

outer join 연산자(+) 를 지정한 table에 대해서는 일시적으로 특별한 null 열이 작성되고

 

통상의 join에서는 return 되지 않는 다른 쪽 table의 행 모두와 join이 일어난다.

 

 

 

outer join 기호는 컬럼명 바로뒤에 붙는다.

 

 

 

null열이 작성되어야 하는 쪽에 기호가 붙는다.

 

그리고 하나의 table이 outer join 의 대상으로 삼을수 있는 table 의 수는 한 개 뿐이다

 

 

 

 

문제4) EMP 테이블과 DEPT 테이블에서 DEPT 테이블에 있는 모든 자료를 사원번호,이름,업무,

 

          EMP 테이블의 부서번호,DEPT 테이블의 부서번호,부서명,근무지를 출력하여라

 

 

1.7 Self Join

 

때때로 자체적으로 테이블을 조인할 필요가 있습니다. 각 종업원의 관리자 명을 알기 위해서

 

자체적으로 EMP테이블을 조인하는 것이 필요합니다.

 

   1)   ENAME열을 검사하여 EMP테이블에서 Blake를 검색한다.

 

   2)   MGR열을 검사하여 Blake에 대한 관리자 번호를 검색한다.(Blake 관리자 번호:7839)

 

   3)   ENAME열을 검사하여 EMPNO가 7839인 관리자를 검색한다.

 

         7839는 King이므로 Blake의 관리자는 King이다.

 

  

☞ Guidelines

 

   1)  Self join을 사용하여 한 테이블의 행들을 같은 테이블의 행들과 조인한다.

 

   2)  같은 테이블에 대해 두 개의 alias를 작성(테이블 구분)함으로 FROM절에 두 개의

 

        테이블을 사용하는 것과 같이 한다.

 

   3)  Column에 대해서도 어떤 테이블에서 왔는지 반드시 Alias명을 기술하여야 한다.

 

   4)  테이블 하나를 두개 또는 그 이상으로 Self join할 수 있다.

 

 

 

문제5) EMP 테이블에서 Self join하여 관리자를 출력하여라.

 

 

[참고..문제1]

 

     temp를 이용하여 자신보다 생일이 빠른 사람의 수를 순서로 정렬하는 QUERY 작성

 

     select

 

     a.emp_id,

 

     to_char(a.birth_date,'yyyy/mm/dd') "일자",

 

     count(b.birth_date) "자신보다 생일이 빠른 사람의 수"

 

     from  temp a, temp b

 

     WHERE b.BIRTH_DATE(+) < a.BIRTH_DATE

 

     GROUP BY a.emp_id,a.birth_date

 

     order by count(b.birth_date);

 

     

 

     19960303     1971/09/25          0

 

     19966102     1972/07/05          1

 

     19930402     1972/08/15          2

 

     19960212     1972/12/15          3

 

     19960101     1973/03/22          4

 

     19950303     1973/06/15          5

 

     19970101     1974/01/25          6

 

     19970201     1975/04/15          7

 

     19930331     1976/05/25          8

 

     19970112     1976/11/05          9

 

 

 

[참고..문제2]

 

     TEMP,TDEPT를 이용하여 상위부서가 'CA0001' 인 부서에 소속된 직원을 나열하시오  

 

     select

 

     a.emp_id       "사번",

 

     a.emp_name "성명",

 

     b.dept_code  "부서",

 

     b.dept_name "부서명",

 

     c.dept_code  "상위",

 

     c.dept_name "상위명",

 

     d.emp_id       "부서장",

 

     d.emp_name "부서장명"

 

     from  temp a, tdept b, tdept c, temp d

 

     where b.dept_code = a.dept_code

 

     and    c.dept_code = b.parent_dept

 

     and    c.dept_code = 'CA0001'

 

     and    d.emp_id     = c.boss_id;  

 

 

 

     사번                         성명  부서       부서명      상위             상위명   부서장            부서장명

 

     19930402     강감찬    CA0001  영업         CA0001            영업       19930402             강감찬

 

     19960303     설까치    CB0001  영업기획 CA0001 영업       19930402             강감찬

 

     19970112     연흥부    CC0001  영업1      CA0001            영업       19930402             강감찬

 

     19960212     배뱅이    CD0001  영업2      CA0001            영업       19930402             강감찬

 

    

 

● subquery (서버 쿼리)

 

    select한 결과를 조건 비교에 사용하거나 update,insert에 사용할 때 사용되는 query를 말한다

 

    종류: single row, multi row, multi column, correlated 4가지가 있다

 

     ■ single row

 

          select에서 결과로 나오는 행의 수가 1 row selected

 

         [예시] select emp_id,emp_name

 

                     from temp

 

                     where salary  = (select max(salary) from temp);

 

     ■ multi row

 

          서버 query결과 나오는 행의 수 >= 1 일 때를 말한다.

 

      이때 in , any , all , exists 등의 연산시에만 가능하다.

 

         [예시] select emp_id,emp_name

 

                     from temp

 

                     where  dept_code in ( select dept_code

 

                                                     from tdept

 

                                                     where area = '인천');

 

   ■ multi column 서버쿼리   

 

          서버 query결과 나오는 행들이 한 컬럼이 아닌 두개 이상을 가지는 경우다.

 

      temp에서 부서별 최고 연봉금액을 읽어서 해당부서와 최고 연봉금액이 동시에

 

      일치하는 사원의 사번,성명,연봉을 읽어라  

 

     [예시] select emp_id,emp_name,salary

 

                    from temp  

 

                    where ( dept_code,salary) in (select dept_code,max(salary)

 

                                                               from temp

 

                                                               group by dept_code);

 

 

 

      ■ correlated 서버쿼리   

 

          innerQuery(sub query)에서 outerQuery(main query)의 어떤 컬럼값을 사용하는 경우를

 

      말한다.

 

      temp 에서 직원중 자신의 연봉이 자신과 같은 LEV(직급)에 해당하는 직원의

 

      평균salary 보다 많은 경우에 이 사원의 사번과 성명을 읽어 오는 query를 작성

 

     [예시] select emp_id,emp_name

 

                    from temp a

 

                    where salary > ( select avg(salary) from temp b

 

                                             where b.lev = a.lev);

 

     [세부해석]

 

    ① 사원table 에서 1 record 가 읽혀진다

 

    ② 해당사원의 직급정보가 innerQuery의 조건에 포함된다

 

    ③ innerQuery가 실행되어 해당직급의 평균연봉이 구해진다

 

    ④ 3번에서 구해진 평균연봉이 1번사원의 연봉과 비교된다

 

    ⑤ 조건을 만족하면 사원번호를 포함하고 아니면 사원번호를 제외한다

 

    ⑥ 다음사원을 읽어 동일한 일을 수행한다

 

    만약 수행속도가 늦으면 correlated 서버쿼리는 반드시 하나의 record가 조건절에서

 

    비교되기 때문에 innerQuery 가 한번씩 수행되어야 하기 때문이다.

 

    즉 10,000건이면 하나의 SQL수행하기 위해 innerQuery가 10,000번 수행하기 때문.

 

                   

 

● exists 사용

 

      subquery 가 적어도 하나의 행을 돌려 주는지를 check하고자 할 때 사용한다.

 

      [예시] select emp_id,emp_name,salary

 

                 from temp a

 

                 where  exists ( select b.salary

 

                                        from temp b

 

                                        where b.lev = '과장'

 

                                        and a.salary > b.salary );    

 

  

 

[CHAPTER 4] 사례 이해를 위한 필수사항     

 

 

 

● rownum 과 rowid  

 

    ■ rownum -> where 까지를 만족시킨 자료에 row 단위로 붙는 순번을 말한다       

 

      [예시1] select rownum,recv_dt,recv_no,ykiho

 

                         from   tbjfc00   

 

              where recv_no > 0  and recv_dt = '20020701' and rownum < 11;  

 

           [예시2] 요양기호중 제일 큰 요양기호를 추출하는 SQL 문장 작성하기.

 

              select /*+ index_desc(TBJCC10  PK_TBJCC10) */ YKIHO

 

              from TBJCC10  

 

              where YKIHO > 0 and rownum = 1;  

 

       [주의] where 에서 rownum 과 관련 =, > , >= 를 사용시 원하는 결과가 나오지 않는다

 

              예외적으로는 rownum = 1 은 사용가능함  

 

    ■ rowid  -> database내의 모든 row 가 가지는 유일한 식별자를 말한다

 

       [구성] oooooo fff bbbbbb sss

 

                       oooooo : 데이터 객체 번호

 

              fff        : 파일번호

 

             bbbbbb : 블록번호

 

             sss      : 슬롯번호        

 

       [예시] 이중고객(DATA중복)을 rowid 를 이용해서 찾는 방법이 있다(많이 활용됨)

 

                         select rowid,cust_id

 

                         from customer a  where a.rowid >

 

                                  (select min(b.rowid) from customer b where a.cust_id = b.cust_id);

 

● decode 문 사용 예시

 

   실제 업무를 하다 보면 DECODE 함수 하나만 사용되는 경우보다는 SUM,MAX,

 

      MIN,COUNT 와 같이 GROUP 함수와 함께 사용되는 경우가 대부분이다   

 

    ■ decode( A , B , 'T' , C , 'F' , 'X' )  

 

            A 컬럼(또는 변수) 과 B 컬럼(또는 변수) 이 같다면 'T' 를 RETURN 받고,

 

            A 컬럼(또는 변수) 과 C 컬럼(또는 변수) 이 같다면 'F' 를 RETURN 받고,

 

       그렇지 않으면 'X'를 RETURN 받는다.

 

    ■ decode에서 OR 비교 예시

 

            decode( A , 0 , '지표' , 1 , '정밀' , 2, '전문','없음')           

 

    ■ decode 에서 AND 비교 예시

 

            decode( A, B , DECODE ( A , C , 'T' , 'F' ) , 'F' )

 

       IF A = B then

 

                IF A = C then

 

                   RETURN 'T';  

 

                else

 

                   RETURN 'F';

 

                end if;

 

            else

 

                RETURN 'F';

 

            end if;  를 의미한다.

 

    ■ decode 에서 중첩IF 예시

 

            decode( A, B , DECODE ( C , D , 'T' , 'F' ) , 'F' )

 

       IF A = B then

 

                IF C = D then

 

                   RETURN 'T';  

 

                else

 

                   RETURN 'F';

 

                end if;

 

            else

 

                RETURN 'F';

 

            end if;  를 의미한다.

 

    ■ group 함수 내의 decode 사용 예시  

 

       temp 의 자료를 이용하여 한 행에 사번,성명을 3명씩 보여주는 SQL 작성

 

       select ceil(rownum / 3) c0,

 

                      max ( decode ( mod ( rownum , 3 ) , 1 , emp_id , null ) )  c1,

 

                      max ( decode ( mod ( rownum , 3 ) , 1 , emp_name , null ) ) c2,

 

                      max ( decode ( mod ( rownum , 3 ) , 2 , emp_id , null ) )  c3,

 

                      max ( decode ( mod ( rownum , 3 ) , 2 , emp_name , null ) ) c4,

 

                      max ( decode ( mod ( rownum , 3 ) , 0 , emp_id , null ) )  c5,

 

                      max ( decode ( mod ( rownum , 3 ) , 0 , emp_name , null ) ) c6

 

            from   temp

 

            where emp_id > 0

 

            group  by ceil(rownum / 3 );

 

            [결과]

 

            C0  C1                     C2  C3                     C4  C5                     C6

 

            1    19930331             정도령  19930402       강감찬  19950303       이순신

 

       2       19960101       홍길동  19960212       배뱅이  19960303       설까치

 

       3       19966102       지문덕  19970101       김길동  19970112       연흥부

 

       4       19970201       박문수                        

 

 

 

● not  in 사용에 있어 함정

 

  ■ where hobby in ( null, '등산')

 

         hobby = null  or hobby = '등산' 으로 해석되는데 hobby = null 은 모두 false return 되고

 

     hobby = '등산' 값만 return 된다. null 은 항상 is null or is not null 로 비교해야 한다.

 

  ■ where hobby not in ( null, '등산')

 

         hobby = null  and hobby = '등산' 으로 해석되는데 hobby = null 가 모두 false return 되므로

 

     not in 에 null 을 포함하면 한 건의 record 도 검색할 수 없다.

 

 

 

● inLine View

 

  ■ inLine View는 view를 이용하는데, create를 시키지 않고 바로 SQL 안에 기술하여 사용

 

     하는 방법을 말한다.

 

       [예시1] 사원table에서 사원을 골라내는데 해당사원의 연봉이 동일한 직급이 가진 사원

 

            의 평균 연봉보다 많은 사원을 찾는 QUERY

 

                     select a.emp_id, a.emp_name, a.salary, b.avg_sal  

 

                     from   temp A ,

 

                              (select lev, avg(salary) avg_sal

 

                               from temp

 

                               group by lev ) B

 

                    where   a.lev = b.lev

 

                    and      a.salary > b.avg_sal;

 

           EMP_ID      EMP_NAME       SALARY         AVG_SAL

 

           19960101    홍길동         72000000        51500000

 

           19950303    이순신         56000000        50500000

 

           19930331    정도령         70000000        67000000

 

 

 

    [예시2] temp 자료에서 rownum 을 채취해 값이 5 와 10 사이에 있는 행의 rownum,

 

                     사번,성명을 조회 SQL 작성 ( inLine View 사용할것 )

 

            select no, emp_id,emp_name

 

                     from   ( select rownum no, emp_id, emp_name

 

                                from  temp

 

                                where emp_id > 0 )

 

                     where  no between 5 and 10;

 

 

 

● hints 란  

 

   optimizer는 수행하고자 하는 DML(select,delete,update,insert)을 가장 효율적으로

 

    처리할 수 있는 최적의 경로를 찾아 주는 것이 주임무다

 

    이러기 위해 필요한 내부요인을 보면

 

    ① 어떤table를 먼저 읽을 것인가

 

    ② table읽을시 index사용할 것인가

 

    ③ index사용시 어떤 index를 사용할 것인가

 

    ④ join 시 어떤 방법 join할 것인가(동등join,outer join, self join )

 

    위와 같은 실행계획에 의거 수핼경로는 PLAN을 통해서 알 수 있다

 

    따라서 hints는 이렇게 optimizer가 실행계획을 작성하는 단계에 인위적으로

 

    개발자가 관여 하겠다는 의도를 가질때 사용된다

 

 

 

  ■ init parameter 중 optimizer_mode 지정하는 값

 

     all_rows

 

         first_rows(현 운영시스템 적용) vi /SYSTEM/ora81/admin/HIRAOPS2/pfile/initHIRAOPS2.ora

 

         choose

 

         rule

 

 

 

  ■ Access Methods 로써의 Hints

 

        full

 

        rowid

 

        hash

 

        hash_aj , hash_sj

 

        index, index_asc, index_desc

 

        index_ffs

 

        merge_aj , merge_sj

 

 

 

    ■ Join 순서를 결정하는 Hints  

 

        ordered

 

        

 

  ■ Join operation을 결정하는 Hints  

 

        use_nl

 

        use_merge

 

 

 

   [ 세부설명은 tuning 과정에서 할 예정임]   

 

 

 

[CHAPTER 5] oracle 8.1.6 이상에서 제공되는 분석용 함수     

 

 

 

● RANKING

 

       RANKING 함수들은 주어진 기준 값에 근거하여 DATASET 내의 다른 RECORD 와

 

    비교되는 RECORD 의 순서를 계산해 낸다.

 

    

 

  

 ■ over             -> 쿼리 result set 을 이용해 동작하는 함수라는 구분이다

 

 ■ partition by   -> result set 을 value expression 에 지정된 값에 근거하여 분할하는 역할함

 

 ■ order by       -> 각 partition 내에서 data가 어떤 값을 기준으로 정렬될 것인가를 지정

 

 ■ nulls first | nulls last   -> null 이 포함된 row 가 순서상 제일 앞에 위치할 것인지 제일

 

                 뒤에 위치할 것인지를 지정

 

 

 

● 실습용 table 생성  

 

 

 

CREATE TABLE SALE_HIST(

 

  SALE_DATE  DATE NOT NULL,               // 매출일자

 

  SALE_SITE  VARCHAR2(10) NOT NULL,  // 매출사업장

 

  SALE_ITEM  VARCHAR2(10) NOT NULL, // 매출품목

 

  SALE_AMT   NUMBER,                          // 매출금액

 

  CONSTRAINT SALEHIST_PK PRIMARY KEY (SALE_DATE,SALE_SITE,SALE_ITEM)

 

);

 

INSERT INTO SALE_HIST VALUES(to_date('20010501','yyyymmdd'),'01','PENCIL',5000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010501','yyyymmdd'),'01','NOTEBOOK',9000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010501','yyyymmdd'),'01','ERASER',4500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010501','yyyymmdd'),'02','PENCIL',2500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010501','yyyymmdd'),'02','NOTEBOOK',7000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010501','yyyymmdd'),'02','ERASER',3000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010501','yyyymmdd'),'03','PENCIL',2500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010501','yyyymmdd'),'03','NOTEBOOK',7000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010501','yyyymmdd'),'03','ERASER',6000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010502','yyyymmdd'),'01','PENCIL',6000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010502','yyyymmdd'),'01','NOTEBOOK',5000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010502','yyyymmdd'),'01','ERASER',5500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010502','yyyymmdd'),'02','PENCIL',3500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010502','yyyymmdd'),'02','NOTEBOOK',7000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010502','yyyymmdd'),'02','ERASER',4000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010502','yyyymmdd'),'03','PENCIL',5500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010502','yyyymmdd'),'03','NOTEBOOK',4500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010502','yyyymmdd'),'03','ERASER',5000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010503','yyyymmdd'),'01','PENCIL',7000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010503','yyyymmdd'),'01','NOTEBOOK',6000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010503','yyyymmdd'),'01','ERASER',6500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010503','yyyymmdd'),'02','PENCIL',3500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010503','yyyymmdd'),'02','NOTEBOOK',5000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010503','yyyymmdd'),'02','ERASER',5000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010503','yyyymmdd'),'03','PENCIL',6500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010503','yyyymmdd'),'03','NOTEBOOK',3500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010503','yyyymmdd'),'03','ERASER',7000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010504','yyyymmdd'),'01','PENCIL',5500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010504','yyyymmdd'),'01','NOTEBOOK',6500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010504','yyyymmdd'),'01','ERASER',3500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010504','yyyymmdd'),'02','PENCIL',7500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010504','yyyymmdd'),'02','NOTEBOOK',5000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010504','yyyymmdd'),'02','ERASER',4000);

 

INSERT INTO SALE_HIST VALUES(to_date('20010504','yyyymmdd'),'03','PENCIL',3500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010504','yyyymmdd'),'03','NOTEBOOK',5500);

 

INSERT INTO SALE_HIST VALUES(to_date('20010504','yyyymmdd'),'03','ERASER',3000);

 

COMMIT;

 

 

 

[실습1] temp 에서 salary 값으로 순위를 부여하는 sql 문 작성

 

 select  emp_id,emp_name,salary,

 

            dense_rank() over (order by salary desc ) as c1,

 

            rank()           over (order by salary desc ) as c2,

 

            rank()           over (order by salary ) as c3  

 

  from temp   

 

 [결과1]

 

 EMP_ID   EMP_NAME     SALARY        C1       C2      C3

 

 19960303 설까치       35000000       9       10      1

 

 19960212 배뱅이       39000000       8       9       2

 

 19966102 지문덕       45000000       7       7       3

 

 19970112 연흥부       45000000       7       7       3

 

 19970201 박문수       50000000       6       6       5

 

 19950303 이순신       56000000       5       5       6

 

 19930402 강감찬       64000000       4       4       7

 

 19930331 정도령       70000000       3       3       8

 

 19960101 홍길동       72000000       2       2       9

 

 19970101 김길동       100000000      1       1       10

 

 [설명1]

 

  RANK 와 DENSE_RANK 의 차이점은 순위를 부여하는 간격에 있다

 

  OVER : 해당함수가 QUERY의 RESULTSET을 이용하여 동작하는 함수라는 표시

 

  ORDER BY : RESULTSET에 순위를 부여할 때의 정렬기준을 표시해 주는 부분

 

 

 

[실습2] temp 에서 직원들을 부서별로 급여기준 순위를 부여하는 sql 문 작성

 

 select  dept_code,emp_id,emp_name,sum(salary),

 

            rank() over (partition by dept_code order by sum(salary) desc ) as c1

 

  from temp   

 

 group  by dept_code,emp_id,emp_name

 

[결과2]

 

 DEPT_CODE     EMP_ID       EMP_NAME  SUM(SALARY)    C1

 

 AA0001 19970101       김길동  100000000      1

 

 AA0001 20000101       이태백  30000000       2

 

 AB0001 19960101       홍길동  72000000       1

 

 AB0001 20000102       김설악  30000000       2

 

 AC0001 19970201       박문수  50000000       1

 

 AC0001 20000203       최오대  30000000       2

 

 BA0001 19930331       정도령  70000000       1

 

 BA0001 20000334       박지리  30000000       2

 

 BB0001 19950303       이순신  56000000       1

 

 BB0001 20000305       정북악  30000000       2

 

 BC0001 19966102       지문덕  45000000       1

 

 BC0001 20006106       유도봉  30000000       2

 

 CA0001 19930402       강감찬  64000000       1

 

 CA0001 20000407       윤주왕  30000000       2

 

 CB0001 19960303       설까치  35000000       1

 

 CB0001 20000308       강월악  30000000       2

 

 CC0001 19970112       연흥부  45000000       1

 

 CC0001 20000119       장금강  30000000       2

 

 CD0001 19960212       배뱅이  39000000       1

 

 CD0001 20000210       나한라  30000000       2

 

 [설명2]

 

  partition by dept_code 라는 문장에 의해 부서별 급여 RANKING이 구해진다

 

  PARTITION BY : 분석용 함수가 작용하는 단위를 표시해 주며 생략될 경우 전체

 

    RESULTSET이 하나의 작용단위가 된다.또한 뒤에 기술된 컬럼에 의하여

 

    분석용 함수가 작용할 단위가 나뉘어지며, 그 안에서 ORDER BY 에 의해

 

    정렬이 이뤄지고 분석용 함수가 작용한다.

 

  

 

[실습3] temp 의 자료를 이용하여 사원별 RANKING을 구하고 부서별로 구한 소계에

 

        까지 RANKING 을 부여해보자

 

        여기서 ROLLUP 이나 CUBE 의 결과로 나오는 SUBTOTAL(소계)에까지 RANKING

 

              이 적용되는지 확인한다   

 

 select  dept_code,emp_id,sum(salary),

 

  rank() over (partition by  grouping (dept_code),

 

                                     grouping (emp_id)

 

                   order by sum(salary) desc ) as c1

 

  from temp   

 

 group  by rollup (dept_code,emp_id);

 

 [결과3]

 

 DEPT_CODE    EMP_ID         SUM(SALARY)      C1

 

 AA0001 19970101     100000000 1

 

 AB0001 19960101       72000000       2

 

 BA0001 19930331       70000000       3

 

 CA0001 19930402       64000000       4

 

 BB0001 19950303       56000000       5

 

 AC0001 19970201       50000000       6

 

 BC0001 19966102       45000000       7

 

 CC0001 19970112       45000000       7

 

 CD0001 19960212       39000000       9

 

 CB0001 19960303       35000000       10

 

 AA0001 20000101       30000000       11

 

 AC0001 20000203       30000000       11

 

 AA0001              130000000 1

 

 AB0001              102000000        2

 

 BA0001              100000000        3

 

 CA0001               94000000        4

 

 BB0001               86000000        5

 

 AC0001               80000000        6

 

 BC0001               75000000        7

 

 CC0001               75000000        7

 

 CD0001               69000000        9

 

 CB0001               65000000        10

 

                             876000000        1

 

 ※ rollup 과 cube 의미

 

 [rollup 예제]

 

 select substr(ykiho,1,2) ykiho12,substr(ykiho,3,1),sum(tot_dmd_cnt)

 

 from   tbjfc02

 

 where  recv_dt between '20020100' and '20020131'

 

 group by  rollup (substr(ykiho,1,2),substr(ykiho,3,1))

 

/

 

SUBSTR(YKIHO,1,2) SUBSTR(YKIHO,3,1)   SUM(TOT_DMD_CNT)

 

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

 

21     2     138155

 

21     3       1562874

 

21      5       216731

 

21      6       18

 

21      7       37682

 

21      8       1801765

 

21      9       186553

 

21             3943778

 

39      2       1488

 

39      3       242614

 

39      5       37928

 

39      7       18463

 

39      8       271618

 

39      9       39530

 

39             611641

 

               4555419

 

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

 

 [cube 예제]

 

select substr(ykiho,1,2),substr(ykiho,3,1),sum(tot_dmd_cnt)

 

from   tbjfc02

 

where  recv_dt between '20020100' and '20020131'

 

group by  cube (substr(ykiho,1,2),substr(ykiho,3,1))

 

/

 

SUBSTR(YKIHO,1,2)      SUBSTR(YKIHO,3,1)      SUM(TOT_DMD_CNT)

 

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

 

21      2       138155

 

21      3       1562874

 

21      5       216731

 

21      6       18

 

21      7       37682

 

21      8       1801765

 

21      9       186553

 

21             3943778

 

39      2       1488

 

39      3       242614

 

39      5       37928

 

39      7       18463

 

39      8       271618

 

39      9       39530

 

39             611641

 

        2       139643

 

        3       1805488

 

        5       254659

 

        6       18

 

        7       56145

 

        8       2073383

 

        9       226083

 

               4555419

 

 

 

 [설명3]

 

 emp_id 만이 null 로 나온 row는 부서별 subtotal 이며 dept_code 까지 null 로 나온것은

 

 grandtotal(합계)이다.

 

 rollup과 cube는 소계및 합계용 함수이고 rollup을 이용해 구해진 소계에도 따로 순위가

 

 부여되는 모습을 보여 주고 있다. 또한 partition by 에 의해 함수 적용단위가 나뉘어지는

 

 경우를 설명하는 좋은 예다

 

 [실습4]

 

 sale_hist table의 자료를 이용하여 일자별 매출 순위와 순위별 사업장,품목을 display 하시오  

 

 select sale_date,sale_site,sale_item,sale_amt,

 

           rank() over ( partition by  sale_date  order by  sale_amt desc ) as c1  

 

  from   sale_hist;

 

 [결과4]

 

SALE_DATE      SALE_SITE      SALE_ITEM      SALE_AMT       C1

 

05/01/2001 00:00:00    01      NOTEBOOK       9000            1

 

05/01/2001 00:00:00    02      NOTEBOOK       7000            2

 

05/01/2001 00:00:00    03      NOTEBOOK       7000            2

 

05/01/2001 00:00:00    03      ERASER         6000            4

 

05/02/2001 00:00:00    02      NOTEBOOK       7000            1

 

05/02/2001 00:00:00    01      PENCIL         6000            2

 

05/02/2001 00:00:00    01      ERASER         5500            3

 

05/02/2001 00:00:00    03      PENCIL         5500            3

 

05/02/2001 00:00:00    01      NOTEBOOK       5000            5

 

 

 

● CUME_DIST

 

     관련 DATASET안에서 해당row의 위치를 0 에서 1 까지의 값으로 표시해 준다.

 

    rank와 비슷하지만 cume_dist는 최대값 1을 기준으로 해당 row의 위치가 0 에서

 

    1 까지의 값으로 표시된다.

 

 

 

● NTILE(n)

 

     자신이 속한 partition 의 row 들을 지정한 숫자만큼으로 분류하고자 할 때 각

 

    row의 위치를 표시한다

 

    예를 들면 100개의 row 에서 ntile(5)하면  1-20(1),21-40(2)..81-100(5)로 분류된다.

 

 

 

● ROW_NUMBER()

 

     partition내의 row 들에 순서대로 unique 한 일련번호를 부여한다.

 

    

 

 [실습1]

 

 temp table 내의 각 row를 salary 기준으로 CUME_DIST,NTILE,ROW_NUMBER의 값을 구하라

 

 select emp_id,emp_name,salary,

 

           rank() over (order by salary ) as c1,

 

           cume_dist()  over ( order by salary ) as c2,

 

           ntile(5)         over ( order by salary ) as c3,

 

           row_number()  over ( order by salary ) as c4

 

  from   temp

 

 [결과1]

 

 EMP_ID EMP_NAME SALARY       C1      C2      C3      C4

 

20000101       이태백  30000000       1       .5      1       1

 

20000102       김설악  30000000       1       .5      1       2

 

20000334       박지리  30000000       1       .5      1       3

 

20000203       최오대  30000000       1       .5      1       4

 

20006106       유도봉  30000000       1       .5      2       5

 

20000308       강월악  30000000       1       .5      2       6

 

20000210       나한라  30000000       1       .5      2       7

 

20000119       장금강  30000000       1       .5      2       8

 

20000407       윤주왕  30000000       1       .5      3       9

 

20000305       정북악  30000000       1       .5      3       10

 

19960303       설까치  35000000       11      .55     3       11

 

19960212       배뱅이  39000000       12      .6      3       12

 

19966102       지문덕  45000000       13      .7      4       13

 

19970112       연흥부  45000000       13      .7      4       14

 

19970201       박문수  50000000       15      .75     4       15

 

19950303       이순신  56000000       16      .8      4       16

 

19930402       강감찬  64000000       17      .85     5       17

 

19930331       정도령  70000000       18      .9      5       18

 

19960101       홍길동  72000000       19      .95     5       19

 

19970101       김길동  100000000      20      1       5       20

 

 

 

● WINDOWING 함수

 

     기존에 있던 모든 그룹 FUNCTION들에 대해서 Moving & Cumulative processing 을

 

    지원하는 함수를 말한다  

 

 

 ■ over             -> 쿼리 result set 을 이용해 동작하는 함수라는 구분이다

 

 ■ partition by   -> result set 을 value expression2 에 지정된 값에 근거하여 분할하는 역할함

 

 ■ order by       -> 각 partition 내에서 data가 어떤 값을 기준으로 정렬될 것인가를 지정

 

 ■ nulls first | nulls last -> null 이 포함된 row 가 순서상 제일 앞에 위치할 것인지 제일

 

                뒤에 위치할 것인지를 지정

 

  ■ rows | range -> 자료의 물리적 순서를 이용(rows)할 것인지 논리적(range)를 이용할 것인지

 

                 를 결정

 

 ■ between.and -> 자료의 범위를 결정한다

 

 ■ unbounded preceding -> 지정된 값 이후의 모든 row를 포함한다

 

 ■ current row   -> 현재 row 를 시작값 또는 마지막 값으로 이용할 때 사용한다.

 

 

 

[실습1] sale_hist 의 자료를 이용하여 '01' 사업장의 품목별 당일 판매액과 당일까지의

 

         누적 판매액을 구하는 SQL 작성( unbounded preceding 사용 )

 

 select  to_char(sale_date,'yyyymmdd') sale_date, sale_site, sale_item,sale_amt,

 

            sum ( sale_amt) OVER

 

            ( PARTITION BY sale_item

 

              ORDER      BY sale_item

 

              ROWS  UNBOUNDED PRECEDING ) as C1

 

  from   sale_hist

 

  where sale_site = '01';

 

[결과1]

 

SALE_DATE SALE_SITE    SALE_ITEM SALE_AMT     C1

 

20010501       01      ERASER     4500 4500

 

20010502       01      ERASER     5500 10000

 

20010503       01      ERASER     6500 16500

 

20010504       01      ERASER     3500 20000

 

20010501       01      NOTEBOOK  9000 9000

 

20010502       01      NOTEBOOK  5000 14000

 

20010503       01      NOTEBOOK  6000 20000

 

20010504       01      NOTEBOOK  6500 26500

 

20010501       01      PENCIL     5000 5000

 

20010502       01      PENCIL     6000 11000

 

20010504       01      PENCIL     5500 16500

 

20010503       01      PENCIL     7000 23500

 

[설명1] unbounded preceding 와 물리적인 이전 rows 참조(rows이용) 를 설명함.

 

 동일 sale_item 에 대하여 정렬하고 동일 sale_item 내에서 자신보다 먼저 나타나는

 

 record들을 이용해 누적sum을 보여주고, rows를 사용하여 물리적인 자료의 순서에 의해

 

 이전 record들을 참조하고 있는 경우를 보여준다

 

 

 

[실습2] 일자별 사업장별 매출액과 사업장별 매출액의 3일 이동평균을 구해보자(range사용)

 

 select to_char(sale_date,'yyyymmdd') sale_date, sale_site,

 

            sum(sale_amt), avg(sum(sale_amt))  OVER

 

       (PARTITION BY sale_site

 

             ORDER BY      sale_date

 

             RANGE INTERVAL  '2'  DAY PRECEDING )  as  S_SUM

 

  from sale_hist

 

  group  by  sale_date, sale_site;

 

[결과2]

 

SITE_DATE SALE_SITE    SUM(SALE_AMT)  S_SUM

 

20010501       01      18500         18500

 

20010502       01      16500         17500

 

20010503       01      19500         18166.66

 

20010504       01      15500         17166.66

 

20010501       02      12500         12500

 

20010502       02      14500        13500

 

20010503       02      13500         13500

 

20010504       02      16500         14833.33

 

20010501       03      15500         15500

 

20010502       03      15000         15250

 

20010503       03      17000         15833.33

 

20010504       03      12000         14666.66

 

[설명2] 논리적인 이전 record 참조의 예이다.

 

 일자별,사업장별로 매출액을 sum한 결과를 이용해 분석함수를 적용시켜 avg 를 구한다

 

 range의 지정범위는 자신의 일자 이전의 2일치 자료와 해당일자의 자료이다.

 

 예를 들면 S_SUM : 17500      =  (18500 + 16500) / 2

 

                                  18166.66 =  (18500 + 16500 + 19500 ) / 3

 

                                  17166.66 =  (16500 + 19500 + 15500 ) / 3   

 

 즉 20010504 면 이전 2일치를 포함된 평균값을 구한다는 의미임

 

 

 

[실습3] TEMP 자료를 이용하여  자신의 급여와 바로 이전 사번 3명의 급여를 이용하여

 

        합계,COUNT,평균을 구해보자 ( rows  N preceding 사용 )

 

 select emp_id, salary,

 

           sum( salary )  OVER

 

                               (ORDER BY emp_id ROWS 3 PRECEDING ) as sum_sal,

 

           count(salary)  OVER

 

                               (ORDER BY emp_id ROWS 3 PRECEDING ) as cnt,

 

           avg(salary)     OVER

 

                   (ORDER BY emp_id ROWS 3 PRECEDING ) as avg

 

  from temp;

 

 [결과3]

 

 EMP_ID             SALARY              SUM_SAL           CNT       AVG

 

19930331             70000000             70000000             1            70000000

 

19930402             64000000             134000000           2            67000000

 

19950303             56000000             190000000           3            63333333.33

 

19960101             72000000             262000000           4            65500000                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                

 

19960212             39000000             231000000           4            57750000

 

19960303             35000000             202000000           4            50500000

 

19966102             45000000             191000000           4            47750000

 

19970101             100000000           219000000           4            54750000

 

19970112             45000000             225000000           4            56250000

 

19970201             50000000             240000000           4            60000000

 

20000101             30000000             225000000           4            56250000

 

20000102             30000000             155000000           4            38750000

 

20000119             30000000             140000000           4            35000000

 

20000203             30000000             120000000           4            30000000

 

20000210             30000000             120000000           4            30000000

 

20000305             30000000             120000000           4            30000000

 

20000308             30000000             120000000           4            30000000

 

20000334             30000000             120000000           4            30000000

 

20000407             30000000             120000000           4            30000000

 

20006106             30000000             120000000           4            30000000

 

[설명3]

 

위의 예시에서 평균 57750000 = ( 640 + 560 + 720 + 390 ) / 4  

 

                   5775     = 2310 / 4  

 

 

 

[실습4] 각 row의 판매액,동일일자/동일품목의 최대판매액,최대판매액사업장,

 

        해당사업장 최소판매액,최소판매액사업장을 구해보자( first_value, last_value 사용 )

 

 

 

 select to_char(sale_date,'yyyymmdd') sale_date,sale_item,sale_site,sale_amt,

 

           first_value(sale_amt) OVER

 

                                        (PARTITION BY sale_date, sale_item

 

                                         ORDER BY      sale_amt

 

                                         ROWS  BETWEEN  UNBOUNDED PRECEDING

 

                                                     AND            UNBOUNDED FOLLOWING

 

                                        ) as  first_amt,

 

        first_value(sale_site) OVER

 

                                        (PARTITION BY sale_date, sale_item

 

                                         ORDER BY      sale_amt

 

                                         ROWS  BETWEEN  UNBOUNDED PRECEDING

 

                                                     AND            UNBOUNDED FOLLOWING

 

                                        ) as  first_site,

 

       last_value(sale_amt) OVER

 

                                        (PARTITION BY sale_date, sale_item

 

                                         ORDER BY      sale_amt

 

                                         ROWS  BETWEEN  UNBOUNDED PRECEDING

 

                                                     AND            UNBOUNDED FOLLOWING

 

                                        ) as  last_amt,

 

            last_value(sale_site) OVER

 

                                        (PARTITION BY sale_date, sale_item

 

                                         ORDER BY      sale_amt

 

                                         ROWS  BETWEEN  UNBOUNDED PRECEDING

 

                                                     AND            UNBOUNDED FOLLOWING

 

                                        ) as  last_site

 

    from sale_hist;

 

[결과4]

 

SALE_DATE SALE_ITEM    SALE_SITE SALE_AMT FIRST_AMT FIRST_SITE LAST_AMT LAST_SITE

 

20010501  ERASER       02         3000 3000      02          6000     03

 

20010501  ERASER       01         4500 3000      02          6000     03

 

20010501  ERASER       03         6000 3000      02          6000     03

 

20010501  NOTEBOOK     02         7000 7000      02          9000     01

 

20010501  NOTEBOOK     03         7000 7000      02          9000     01

 

20010501  NOTEBOOK     01         9000 7000      02          9000     01

 

20010501  PENCIL       02         2500 2500      02          5000     01

 

20010501  PENCIL       03         2500 2500      02          5000     01

 

20010501  PENCIL       01         5000 2500      02          5000     01

 

20010502  ERASER       02         4000 4000      02          5500     01

 

20010502  ERASER       03         5000 4000      02          5500     01

 

20010502  ERASER       01         5500 4000      02          5500     01

 

20010502  NOTEBOOK     03         4500 4500      03          7000     02

 

20010502  NOTEBOOK     01         5000 4500      03          7000     02

 

20010502  NOTEBOOK     02         7000 4500      03          7000     02

 

20010502  PENCIL       02         3500 3500      02          6000     01

 

20010502  PENCIL       03         5500 3500      02          6000     01

 

20010502  PENCIL       01         6000 3500      02          6000     01

 

[설명4]

 

first_value, last_value 의 의미를 이해하기 위한 예제이며,

 

first_value -> partition by 에 의해 분류된 범위내에서 order by 절에 정렬을 한 후 rows 또는

 

           range에 의해 범위가 지정되면 그 중 제일 앞에 위치하는 row의 값들을 읽어온다

 

last_value -> 상동.이하생략...그 중 제일 뒤에 위치하는 row의 값들을 읽어온다.

 

즉 first_value와 last_value는 정렬된 row의 순서에 의해 값이 결정된다.

 

확인 방법은 order by 뒤에 desc 를 붙여서 결과를 보면된다.

 

 

 

[실습5] 일자별 매출액과 함께 각 일자의 매출액이 전체일자 매출액에서 차지하는 비율을 구한다

 

        ( ratio_to_report 사용 )

 

 select to_char(sale_date,'yyyymmdd') sale_date,

 

           sum(sale_amt)  as sale_amt,

 

           sum(sum(sale_amt)) OVER ( )  as sum_tot,

 

           round( ratio_to_report ( sum(sale_amt)) OVER ( ) ,2)  as c1

 

  from   sale_hist

 

  group by sale_date;

 

 [결과5]

 

SALE_DATE        SALE_AMT          SUM_TOT            C1

 

20010501             46500                 186500      .25

 

20010502             46000                 186500                    .25

 

20010503             50000                 186500                    .27

 

20010504             44000                 186500                    .24

 

[설명5]

 

 ratio_to_report 라는 함수가 전체대비 해당 row의 값이 차지하는 비율을 구해준다

 

  위에서 처럼 소숫점 2자리까지만 나타날때 round를 사용한다

 

 

 

[실습6] 사업장별 품목의 매출액과 함께 동일사업장 동일품목의 전일 매출액과 다음날 매출액을

 

        구한다 ( LAG 와 LEAD 사용 )  

 

 select to_char(sale_date,'yyyymmdd') sale_date, sale_site,sale_item, sale_amt,

 

           lag(sale_amt,1)  OVER

 

                                  (PARTITION BY sale_site, sale_item

 

                                   ORDER BY sale_date, sale_site,sale_item) as LAG_AMT,

 

           lead(sale_amt,1)  OVER

 

                                  (PARTITION BY sale_site, sale_item

 

                                   ORDER BY sale_date, sale_site,sale_item) as LEAD_AMT

 

    from   sale_hist;       

 

 [결과6]

 

SALE_DATE      SALE_SITE SALE_ITEM    SALE_AMT LAG_AMT LEAD_AMT

 

20010501       01         ERASER      4500           5500

 

20010502       01         ERASER      5500      4500         6500

 

20010503       01         ERASER      6500      5500         3500

 

20010504       01         ERASER      3500      6500  

 

20010501       01         NOTEBOOK    9000           5000

 

20010502       01         NOTEBOOK    5000      9000         6000

 

20010503       01         NOTEBOOK    6000     5000 6500

 

20010504       01         NOTEBOOK    6500      6000  

 

20010501       01         PENCIL      5000                   6000

 

20010502       01         PENCIL      6000      5000         7000

 

20010503       01         PENCIL      7000     6000 5500

 

20010504       01         PENCIL      5500      7000  

 

[설명6]

 

lag는 바로 이전 값을 참조하고, lead 는 바로 이후 값을 참조한다

 

lag와 lead 함수 안에 지정되는 숫자가 각각 앞뒤로 몇번째 row를 참조할 것인지를 결정

 

 

 

[실습7] sale_hist 에서 '01'사업장, 'PENCIL' 품목의 일자별 누적 판매금액을 구하라  

 

 select to_char(sale_date,'yyyymmdd') sale_date, sale_amt,

 

           sum(sale_amt)  OVER

 

                                  (ORDER BY sale_date

 

                                   ROWS  UNBOUNDED  PRECEDING ) as c1

 

   from   sale_hist

 

   where sale_site  = '01'

 

   and    sale_item = 'PENCIL';

 

 [결과6]

 

SALE_DATE      SALE_AMT       C1

 

20010501       5000   5000

 

20010502       6000          11000

 

20010503       7000         18000

 

20010504       5500         23500

 

 

 

[실습8] sale_hist 에서 품목별/일자별로 과거 판매액을 모두 이용하여 이동평균값을 구하라  

 

 select sale_item,to_char(sale_date,'yyyymmdd') sale_date, sum(sale_amt),

 

           avg(sum(sale_amt))   OVER

 

                                        ( PARTITION BY sale_item

 

                                          ORDER BY sale_date

 

                                          ROWS  UNBOUNDED  PRECEDING ) as s_sum

 

   from   sale_hist

 

   group by sale_item, sale_date;

 

[결과8]

 

SALE_ITEM SALE_DATE SUM(SALE_AMT) S_SUM

 

ERASER             20010501             13500          13500

 

ERASER             20010502             14500          14000

 

ERASER             20010503             18500          15500

 

ERASER             20010504             10500          14250

 

NOTEBOOK        20010501             23000          23000

 

NOTEBOOK        20010502             16500          19750

 

NOTEBOOK        20010503             14500          18000

 

NOTEBOOK        20010504             17000          17750

 

PENCIL              20010501             10000          10000

 

PENCIL              20010502     15000          12500

 

PENCIL              20010503     17000          14000

 

PENCIL              20010504     16500          14625

 

 

 

[실습9] sale_hist 에서 '01'사업장, 'PENCIL' 품목에 대해 일자별 매출액과 전일매출액,

 

        당일과 전일매출액과의 차이를 구하시오     

 

 select to_char(sale_date,'yyyymmdd') sale_date, sale_amt,

 

            lag(sale_amt,1)  OVER

 

                                   (ORDER BY sale_date ) as yest_amt,

 

            sale_amt -

 

            lag(sale_amt,1)  OVER

 

                                   (ORDER BY sale_date ) as diff_amt

 

  from   sale_hist

 

  where sale_site   = '01'

 

  and    sale_item  = 'PENCIL';

 

[결과9]

 

SALE_DATE      SALE_AMT       YEST_AMT  DIFF_AMT

 

20010501       5000           

 

20010502       6000           5000       1000

 

20010503       7000           6000       1000

 

20010504       5500           7000      -1500

 

 

 

● CASE 함수

 

  기존 DECODE 문을 CASE를 통해 보다 간편하게 처리될 수 있다

 

 [실습1] temp 자료를 salary로 분류하여 30000000 이하면 'D'

 

                                                                  30000000 초과 50000000 이하는 'C'

 

                                                                  50000000 초과 70000000 이하는 'B'

 

                                                                  70000000 초과는 'A' 라는 등급을 분류하여

 

         인원수를 알고 싶다

 

 select  CASE WHEN  salary <= 30000000 THEN   'D'

 

                       WHEN  salary BETWEEN 30000001  AND  50000000 THEN  'C'  

 

                       WHEN  salary BETWEEN 50000001  AND  70000000 THEN  'B'  

 

                       WHEN  salary > 70000000  THEN   'A'  END,

 

             COUNT(*)

 

   from  temp

 

   group  by  

 

             CASE WHEN  salary <= 30000000 THEN   'D'

 

                       WHEN  salary BETWEEN 30000001  AND  50000000 THEN  'C'  

 

                       WHEN  salary BETWEEN 50000001  AND  70000000 THEN  'B'  

 

                       WHEN  salary > 70000000  THEN   'A'  END;

 

[결과1]

 

CASEWHENSALARY<=30000000THEN'D COUNT(*)

 

A                                  2

 

B                                  3

 

C                                  5

 

D                                 10

 

 

 

[실습2] temp 자료를 salary로 분류하여 30000000 이하면 'D'

 

                                                                  30000000 초과 50000000 이하는 'C'

 

                                                                  50000000 초과 70000000 이하는 'B'

 

                                                                  70000000 초과는 'A' 라는 등급을 분류하여

 

         인원수를 알고 싶다 (단 행단위로 나오는 값을 컬럼단위로 표현한다)

 

 select  count ( CASE WHEN  salary > 70000000                                       THEN   'A'  END) as  A,

 

            count ( CASE WHEN  salary BETWEEN 50000001  AND  70000000 THEN  'B'  END)  as  B,

 

            count ( CASE WHEN  salary BETWEEN 30000001  AND  50000000 THEN  'C'  END)  as  C,

 

            count ( CASE WHEN  salary <= 30000000                                      THEN  'D'  END)  as  D

 

  from  temp;

 

[결과2]

 

A       B       C       D

 

2       3       5       10

 

 

 

[실습3]sale_hist 에서 일자별 품목별로

 

       '01','02' 사업장 판매 금액합,

 

       '02','03' 사업장 판매 금액합을 구하시오

 

 select  to_char(sale_date,'yyyymmdd') sale_date, sale_item,

 

             sum( CASE  WHEN  sale_site  BETWEEN  '01' AND '02' THEN sale_amt  END) as S01,

 

             sum( CASE  WHEN  sale_site  BETWEEN  '02' AND '03' THEN sale_amt  END) as S02

 

  from    sale_hist

 

  group  by  sale_date, sale_item;

 

[결과3]

 

SALE_DATE      SALE_ITEM       S01      S02

 

20010501       ERASER          7500   9000

 

20010501       NOTEBOOK       16000   14000

 

20010501       PENCIL          7500   5000

 

20010502       ERASER          9500   9000

 

20010502       NOTEBOOK       12000   11500

 

20010502       PENCIL          9500   9000

 

20010503       ERASER         11500   12000

 

20010503       NOTEBOOK       11000   8500

 

20010503       PENCIL         10500   10000

 

20010504       ERASER          7500   7000

 

20010504       NOTEBOOK       11500   10500

 

20010504       PENCIL         13000   11000

 

 

 

● 함수들 모음

 

    ■ 통계 함수

 

       -> var_pop         : 모집단의   분산을 구해준다

 

       -> avr_samp      : 표본집단의 분산을 구해준다

 

       -> stddev_pop    : 모집단의   표준편차를 구해준다

 

       -> stddev_samp : 표본집단의 표준편차를 구해준다

 

       -> corvar_pop     : 모집단의   공 분산을 구해준다

 

       -> corvar_samp  : 표본집단의 공 분산을 구해준다

 

       -> corr               : 상관계수을 구해준다

 

     ■ 회귀 분석용 함수           

 

             ->  regr_count     : 회귀선상에 찍히는 값들의 숫자를 구해준다

 

       -> regr_avgy, regr_avgx  : 회귀선의 독립변수와 종속변수의 평균을 구해준다

 

       -> regr_slope, regr_intercept  : 회귀선의 기울기를 구해준다

 

       -> regr_r2   : 회귀선의 적합도를 구해준다

 

       -> regr_sxx, regr_syy,  regr_sxy  : 회귀분석용 함수         

 

http://163.163.31.21:9001/common/web/mainframe.jsp

 

 

 

'(DB) Oracle > SQL' 카테고리의 다른 글

Oracle - 예제_CASE_예제1  (0) 2017.01.18
Oracle - 예제_JOIN  (0) 2017.01.18
Oracle - 예제_UPDATE  (0) 2017.01.18
Oracle - 예제_SUBQUERY  (0) 2017.01.18
Oracle - 예제_SELECT_GROUP  (0) 2017.01.18
Posted by 농부지기
,

                              [ UPDATE 문 ]

 

여러컬럼 UPDATE

 

UPDATE  table_name
  
SET ( col1, col2, col3, .. ColN ) =  ( UPDATE any_style_logical_column, ...
                                         
FROM   other_table1, ... , other_tableN
                                         
WHERE  join_conditions ...
                                         
AND    sub_query_column = main_query_column...)
WHERE  (column, ... ) IN ( UPDATE  join_column,...
                           
FROM    tables
                           
WHERE   conditions ..... )

SELECT 문을 이용한 UPDATE

 

1. UPDATE 문에는   FROM 절이 올 수 없다..
1. 배분후 잔량을 한번에 처리하는 SQL 문장...

UPDATE TBL_MNTH_DIVI_LOSS_WEIGHT a
SET    LOSS_SEPA_WEIGHT = LOSS_SEPA_WEIGHT +  
       NVL(( SELECT (X.LOSS_WEIGHT - X.LOSS_SEPA_WEIGHT_SUM )
             FROM   (
SELECT MANG_YYYYMM, MAX(DIVI_CODE_ITEM) AS DIVI_CODE_ITEM, MATR_CODE,
                             LOT_NO_MATR, LOSS_WEIGHT,
                             SUM(LOSS_SEPA_WEIGHT)AS LOSS_SEPA_WEIGHT_SUM
                      
FROM   TBL_MNTH_DIVI_LOSS_WEIGHT B
                      
WHERE  B.MANG_YYYYMM = :ls_yymm
                      
GROUP  BY MANG_YYYYMM, MATR_CODE, LOT_NO_MATR, LOSS_WEIGHT
                      
HAVING LOSS_WEIGHT       <> SUM(LOSS_SEPA_WEIGHT)  ) X
                      
WHERE  a.MANG_YYYYMM     =  x.MANG_YYYYMM
                      
AND    a.DIVI_CODE_ITEM  = x.DIVI_CODE_ITEM
                      
AND    a.MATR_CODE       = x.MATR_CODE
                      
AND    a.LOT_NO_MATR     = x.LOT_NO_MATR ), 0) ;

 
 

 

 

'(DB) Oracle > SQL' 카테고리의 다른 글

Oracle - 예제_JOIN  (0) 2017.01.18
Oracle - 예제_LEAD.LAG  (0) 2017.01.18
Oracle - 예제_SUBQUERY  (0) 2017.01.18
Oracle - 예제_SELECT_GROUP  (0) 2017.01.18
Oracle - 예제_SELECT  (0) 2017.01.18
Posted by 농부지기
,

                             [ SELECT SUBQUERY 예제 ]

 

☞ SUBQUERY의 개념

 

ㅇ SUBQUERY : 하나의 SELECT(SQL)문 안에 포함되어 있는 SELECT 문장
ㅇ SUBQUERY의 종류 : Nested Subquery, Correlated Subquery
ㅇ SUBQUERY의 문항 : Subquery는 괄호로 묶여 있어야 합니다.
                   : Subquery구문에서는 ORDER BY절을 포함할 수 없습니다.
                   : Subquery는 일반적으로 연산자의 오른쪽에 위치합니다.
                   : Subquery에서 사용할 수 있는 연산자의 종류에는
                      - 단일행 연산자(=, >, >=, <, <=, <>)
                      - 복수행연산자 (IN ,ANY , ALL , NOT IN , ... )가 있습니다.

 

ㅇ Single Row Subquery : Subquery에서 Main Query로 전달되는 행이 단 하나인 경우

 

ㅇ Multi Column Subquery : Subquery구문을 작성할 때 WHERE절에서 비교하는 컬럼이 하나가 아니라
                           여러 개의 컬럼을 동시에 비교하는 경우를 말하며 이런 경우
                           Pairwise되었다라고 함.

 

ㅇ Scalar Subquery : Subquery에 의해 하나의 행, 하나의 칼럼 값이 Return 되어지는 경우를 말함.

 

ㅇ Correated Subquery : Main에서 자신의 데이터를 넘겨주고 Subquery가 이를 처리하여 돌려주는 방식
                      : Main의 각 행에 대해 마지막 행에 도달할 때까지 반복 수행되는 Subquery

 

☞ Single Row Subquery

 

   예시) SQL>SELECT name, title , dept_id
            
FROM   EMPLOYEE   
            
WHERE  dept_id = ( SELECT dept_id          
                                
FROM   EMPLOYEE
                                
WHERE
name = ‘김용학’ )  ;

☞  Multi Row Subquery

 

1) IN : 한번에 여러 OR로 동일(=)하기 비교하는 연산자
   예시) SQL>
SELECT   name,  dept_id
            
FROM  s_emp
            
WHERE  dept_id IN ( SELECT dept_id
                                 
FROM s_dept
                                 
WHERE region_id =3 )  ;

2) ANY(ALL) : 값을 Subquery에 의해 반환되는 각각의 값과 비교
    예시) 직책이 사원이 아니면서 사원이 받고 있는 어떤(모든) 급여보다도 적은 급여를 받는
          사원의 이름, 급여, 직책을 나타내시오.
          SQL>
SELECT name, salary, title
               
FROM   EMPLOYEE
               
WHERE  salary  < ANY  ( SELECT salary
                                
       FROM   EMPLOYEE
                                       
WHERE  title = '사원' )
               
AND    title <> '사원' ;
     ※ = ANY는 IN과 동일

     예시)SQL>
SELECT  name , salary , title
               
FROM    EMPLOYEE
               
WHERE salary  < ALL  ( SELECT salary
                                      
FROM   EMPLOYEE
                                      
WHERE title = '사원' )
               
AND title <> '사원' ; 
     ※ ALL는 최대값보다 큼을, <
ALL는 최소값보다 적음을 나타낸다.

☞ Multi Column Subquery

 

예시) 각 부서별로 최소급여를 받는 사원의 이름, 부서번호, 급여를 나타내시오.
    SQL>
SELECT name, dept_id, salary
         
FROM   EMPLOYEE
         
WHERE (salary,dept_id) IN  (SELECT MIN(salary),dept_id
                                     
FROM   EMPLOYEE
                                     
GROUP BY dept_id );

☞ Scalar Subquery

 

   예시 1) SQL> SELECT name, salary , (SELECT AVG(salary) FROM EMPLOYEE ) avg_sal
                
FROM   EMPLOYEE ;

   예시 2) SQL>
SELECT name, salary , CASE WHEN  salary >  ( SELECT avg(salary)
                                                             FROM
 EMPLOYEE)  
                                           
THEN salary * 1.1
                                           
ELSE  salary*1.2
                                           
END  bonus
                    , title
                
FROM  EMPLOYEE ;

   예시 3) SQL>
SELECT id , name , dept_id
                
FROM   EMPLOYEE e
                
WHERE  salary >= 2500
                
ORDER BY ( SELECT name
                           
FROM   T_dept d
                           
WHERE  e.dept_id = d.dept_id ) ;

☞ Correated Subquery

 

SQL> SELECT name, salary ,dept_id
     
FROM   EMPLOYEE  outer
     
WHERE  salary < (SELECT AVG(salary)
                      
FROM   EMPLOYEE

                      
WHERE  dept_id = outer.dept_id ) ;

   ※ 바로 2번째 Line의 Outer라는 테이블 Alias를 5번 Line에서 사용하게 되면 내부적으로
      Correlated Subquery의 진행방식을 따르게 됨.

   ㅇ 연산자 EXIST, NOT EXISTS
      예시) SQL>
SELECT id, name , title , dept_id
                 
FROM   EMPLOYEE  o
                 
WHERE  EXISTS ( SELECT 'X' 
                                 
FROM   EMPLOYEE

                                 
WHERE  manager_id = o.id ) ;

      예시) SQL>
SELECT id, name , title , dept_id
                 
FROM   EMPLOYEE
                 
WHERE  id IN  ( SELECT manager_id
                                 
FROM   EMPLOYEE

                                 
WHERE  manager_id IS NOT NULL ) ;

 




 

'(DB) Oracle > SQL' 카테고리의 다른 글

Oracle - 예제_LEAD.LAG  (0) 2017.01.18
Oracle - 예제_UPDATE  (0) 2017.01.18
Oracle - 예제_SELECT_GROUP  (0) 2017.01.18
Oracle - 예제_SELECT  (0) 2017.01.18
Oracle - 예제_MERGE  (0) 2017.01.18
Posted by 농부지기
,