분석함수 : RANK, DENSE_RANK, LAG, LEAD 
RANK() OVER (PARTITION BY 컬럼명 ORDER BY 컬럼명) 
 
 
The sql extension is already loaded. To reload it, use:
  %reload_ext sql
 
1 %sql oracle://ora_user:evan@127.0 .0 .1 :1521 /myoracle 
 
분석 함수: 분석 함수 역시 특정 그룹별 집계를 담당하므로 집계 함수에 속한다. 
 
PARTITION BY 절: 분석 함수로 계산될 대상 로우의 그룹(파티션)을 지정한다.
 
ORDER BY 절: 파티션 안에서의 순서를 지정한다.
 
WINDOW 절: 파티션으로 분할된 그룹에 대해서 더 상세한 그룹으로 분할할 때 사용된다. # Window 절 
 
ROWS: 로우 단위로 window 절을 지정한다.
 
RANGE: 로우가 아닌 논리적인 범위로 window 절을 지정한다.
 
BETWEEN~AND: window 절의 시작과 끝 지점을 명시한다.          BETWEEN을 명시하지 않고 두 번째 옵션만 지정하면이 지점이 시작 지점이 되고 끝 지점은 현재 로우가 된다.
 
UNBOUNDED PRECEDING: 파티션으로 구분된 첫 번째 로우가 시작 지점이 된다.
 
UNBOUNDED FOLLOWING: 파티션으로 구분된 마지막 로우가 끝 지점이 된다.
 
CURRENT ROW: 시작 및 끝 지점이 현재 로우가된다.
 
value_expr PRECEDING: 끝 지점일 경우, 시작 지점은 value_expr PRECEDING.
 
value_expr FOLLOWING: 시작 지점일 경우, 끝 지점은 value_expr FOLLOWING.
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 % % sql SELECT     department_id     , emp_name     , hire_date     , salary     , SUM (salary) OVER  (PARTITION  BY  department_id                         ORDER  BY  hire_date                         ROWS  BETWEEN  UNBOUNDED PRECEDING AND  UNBOUNDED FOLLOWING) AS  all_salary     , SUM (salary) OVER  (PARTITION  BY  department_id                         ORDER  BY  hire_date                         ROWS  BETWEEN  UNBOUNDED PRECEDING AND  CURRENT  ROW ) AS  first_current_sal     , SUM (salary) OVER  (PARTITION  BY  department_id                         ORDER  BY  hire_date                         ROWS  BETWEEN  CURRENT  ROW  AND  UNBOUNDED FOLLOWING) AS  current_end_sal FROM  employeesWHERE  department_id IN  (30 , 90 )
 
 * oracle://ora_user:***@127.0.0.1:1521/myoracle
0 rows affected.
 
    
        department_id 
        emp_name 
        hire_date 
        salary 
        all_salary 
        first_current_sal 
        current_end_sal 
     
    
        30 
        Den Raphaely 
        2002-12-07 00:00:00 
        11000 
        24900 
        11000 
        24900 
     
    
        30 
        Alexander Khoo 
        2003-05-18 00:00:00 
        3100 
        24900 
        14100 
        13900 
     
    
        30 
        Sigal Tobias 
        2005-07-24 00:00:00 
        2800 
        24900 
        16900 
        10800 
     
    
        30 
        Shelli Baida 
        2005-12-24 00:00:00 
        2900 
        24900 
        19800 
        8000 
     
    
        30 
        Guy Himuro 
        2006-11-15 00:00:00 
        2600 
        24900 
        22400 
        5100 
     
    
        30 
        Karen Colmenares 
        2007-08-10 00:00:00 
        2500 
        24900 
        24900 
        2500 
     
    
        90 
        Lex De Haan 
        2001-01-13 00:00:00 
        17000 
        58000 
        17000 
        58000 
     
    
        90 
        Steven King 
        2003-06-17 00:00:00 
        24000 
        58000 
        41000 
        41000 
     
    
        90 
        Neena Kochhar 
        2005-09-21 00:00:00 
        17000 
        58000 
        58000 
        17000 
     
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 % % sql SELECT     department_id     , emp_name     , hire_date     , salary     , FIRST_VALUE (salary) OVER  (PARTITION  BY  department_id                         ORDER  BY  hire_date                         ROWS  BETWEEN  UNBOUNDED PRECEDING AND  UNBOUNDED FOLLOWING) AS  all_salary     , FIRST_VALUE (salary) OVER  (PARTITION  BY  department_id                         ORDER  BY  hire_date                        ROWS  BETWEEN  UNBOUNDED PRECEDING AND  CURRENT  ROW ) AS  first_current_sal     , FIRST_VALUE (salary) OVER  (PARTITION  BY  department_id                         ORDER  BY  hire_date                         ROWS  BETWEEN  CURRENT  ROW  AND  UNBOUNDED FOLLOWING) AS  current_end_sal FROM  employeesWHERE  department_id IN  (30 , 90 )
 
 * oracle://ora_user:***@127.0.0.1:1521/myoracle
0 rows affected.
 
    
        department_id 
        emp_name 
        hire_date 
        salary 
        all_salary 
        first_current_sal 
        current_end_sal 
     
    
        30 
        Den Raphaely 
        2002-12-07 00:00:00 
        11000 
        11000 
        11000 
        11000 
     
    
        30 
        Alexander Khoo 
        2003-05-18 00:00:00 
        3100 
        11000 
        11000 
        3100 
     
    
        30 
        Sigal Tobias 
        2005-07-24 00:00:00 
        2800 
        11000 
        11000 
        2800 
     
    
        30 
        Shelli Baida 
        2005-12-24 00:00:00 
        2900 
        11000 
        11000 
        2900 
     
    
        30 
        Guy Himuro 
        2006-11-15 00:00:00 
        2600 
        11000 
        11000 
        2600 
     
    
        30 
        Karen Colmenares 
        2007-08-10 00:00:00 
        2500 
        11000 
        11000 
        2500 
     
    
        90 
        Lex De Haan 
        2001-01-13 00:00:00 
        17000 
        17000 
        17000 
        17000 
     
    
        90 
        Steven King 
        2003-06-17 00:00:00 
        24000 
        17000 
        17000 
        24000 
     
    
        90 
        Neena Kochhar 
        2005-09-21 00:00:00 
        17000 
        17000 
        17000 
        17000 
     
p.211 
계층형 쿼리 
핵심 포인트 : CONNECT BY 조건문 정리- 계층형 쿼리의 구문은 다음과 같다. 
 
SELECT expr1, expr2, … FROM 테이블 WHERE 조건 START WITH[최상위 조건] CONNECT BY [NOCYCLE][PRIOR 계층형 구조 조건];       –> 구조 :  CONNECT BY PRIOR 하위 = 상위 
START WITH 조건
계층형 구조에서 최상위 계층의 로우를 식별하는 조건을 명시한다.  
START WITH가 시작한다는 의미이므로, 이 조건에 맞는 로우부터 시작해 계층형 구조를 풀어 나간다. 
 
 
CONNECT BY 조건
계층형 구조가 어떤 식으로 연결되는지를 기술하는 부분이다. 
부서 테이블은 parent_id에 상위 부서 정보를 갖고 있는데,   이를 표현하려면 ‘CONNECT BY PRIOR department_id = parent_id’로 기술해야 한다.  
PRIOR는 계층형 쿼리에서만 사용할 수 있는 연산자로 ‘앞서의, 직전의’란 뜻이 있으므로,   “이전 department_id = parent_id”라고 알아두면 이해하기 쉬울 것이다.  
또한 ‘CONNECT BY parent_id = PRIOR department_id’처럼 PRIOR의 위치를 바꿀 수 있다. 
 
 
 
1 2 3 4 5 6 7 8 9 % % sql SELECT     department_id     , LPAD(' ' , 3 * (LEVEL-1 )) ||  department_name     , LEVEL FROM  departmentsSTART  WITH  parent_id IS  NULL CONNECT  BY  PRIOR department_id =  parent_id 
 
 * oracle://ora_user:***@127.0.0.1:1521/myoracle
0 rows affected.
 
    
        department_id 
        LPAD('',3*(LEVEL-1))||DEPARTMENT_NAME 
        LEVEL 
     
    
        10 
        총무기획부 
        1 
     
    
        20 
           마케팅 
        2 
     
    
        30 
           구매/생산부 
        2 
     
    
        170 
              생산팀 
        3 
     
    
        180 
              건설팀 
        3 
     
    
        200 
              운영팀 
        3 
     
    
        210 
              IT 지원 
        3 
     
    
        220 
              NOC 
        3 
     
    
        40 
           인사부 
        2 
     
    
        260 
              채용팀 
        3 
     
    
        50 
           배송부 
        2 
     
    
        80 
           영업부 
        2 
     
    
        190 
              계약팀 
        3 
     
    
        240 
              공공 판매사업팀 
        3 
     
    
        250 
              판매팀 
        3 
     
    
        90 
           기획부 
        2 
     
    
        60 
              IT 
        3 
     
    
        230 
                 IT 헬프데스크 
        4 
     
    
        70 
              홍보부 
        3 
     
    
        100 
              자금부 
        3 
     
    
        130 
                 세무팀 
        4 
     
    
        140 
                 신용관리팀 
        4 
     
    
        150 
                 주식관리팀 
        4 
     
    
        160 
                 수익관리팀 
        4 
     
    
        110 
              경리부 
        3 
     
    
        120 
                 재무팀 
        4 
     
    
        270 
                 급여팀 
        4 
     
manager_id는 해당 사원의 매니저 사번이 있다. 
각 매니저는 사원 ID가 있다. 
사원별 계층 구조를 만들고, 부서 테이블과 조인해서 부서명까지 조회한다. 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 % % sql SELECT      a.employee_id     , LPAD(' ' , 3  *  (LEVEL -  1 )) ||  a.emp_name     , LEVEL     , b.department_name FROM     employees a     , departments b WHERE  a.department_id =  b.department_idSTART  WITH  a.manager_id IS  NULL CONNECT  BY  PRIOR a.employee_id =  a.manager_id
 
 * oracle://ora_user:***@127.0.0.1:1521/myoracle
0 rows affected.
 
    
        employee_id 
        LPAD('',3*(LEVEL-1))||A.EMP_NAME 
        LEVEL 
        department_name 
     
    
        100 
        Steven King 
        1 
        기획부 
     
    
        101 
           Neena Kochhar 
        2 
        기획부 
     
    
        108 
              Nancy Greenberg 
        3 
        자금부 
     
    
        109 
                 Daniel Faviet 
        4 
        자금부 
     
    
        110 
                 John Chen 
        4 
        자금부 
     
    
        111 
                 Ismael Sciarra 
        4 
        자금부 
     
    
        112 
                 Jose Manuel Urman 
        4 
        자금부 
     
    
        113 
                 Luis Popp 
        4 
        자금부 
     
    
        200 
              Jennifer Whalen 
        3 
        총무기획부 
     
    
        203 
              Susan Mavris 
        3 
        인사부 
     
    
        204 
              Hermann Baer 
        3 
        홍보부 
     
    
        205 
              Shelley Higgins 
        3 
        경리부 
     
    
        206 
                 William Gietz 
        4 
        경리부 
     
    
        102 
           Lex De Haan 
        2 
        기획부 
     
    
        103 
              Alexander Hunold 
        3 
        IT 
     
    
        104 
                 Bruce Ernst 
        4 
        IT 
     
    
        105 
                 David Austin 
        4 
        IT 
     
    
        106 
                 Valli Pataballa 
        4 
        IT 
     
    
        107 
                 Diana Lorentz 
        4 
        IT 
     
    
        114 
           Den Raphaely 
        2 
        구매/생산부 
     
    
        115 
              Alexander Khoo 
        3 
        구매/생산부 
     
    
        116 
              Shelli Baida 
        3 
        구매/생산부 
     
    
        117 
              Sigal Tobias 
        3 
        구매/생산부 
     
    
        118 
              Guy Himuro 
        3 
        구매/생산부 
     
    
        119 
              Karen Colmenares 
        3 
        구매/생산부 
     
    
        120 
           Matthew Weiss 
        2 
        배송부 
     
    
        125 
              Julia Nayer 
        3 
        배송부 
     
    
        126 
              Irene Mikkilineni 
        3 
        배송부 
     
    
        127 
              James Landry 
        3 
        배송부 
     
    
        128 
              Steven Markle 
        3 
        배송부 
     
    
        180 
              Winston Taylor 
        3 
        배송부 
     
    
        181 
              Jean Fleaur 
        3 
        배송부 
     
    
        182 
              Martha Sullivan 
        3 
        배송부 
     
    
        183 
              Girard Geoni 
        3 
        배송부 
     
    
        121 
           Adam Fripp 
        2 
        배송부 
     
    
        129 
              Laura Bissot 
        3 
        배송부 
     
    
        130 
              Mozhe Atkinson 
        3 
        배송부 
     
    
        131 
              James Marlow 
        3 
        배송부 
     
    
        132 
              TJ Olson 
        3 
        배송부 
     
    
        184 
              Nandita Sarchand 
        3 
        배송부 
     
    
        185 
              Alexis Bull 
        3 
        배송부 
     
    
        186 
              Julia Dellinger 
        3 
        배송부 
     
    
        187 
              Anthony Cabrio 
        3 
        배송부 
     
    
        122 
           Payam Kaufling 
        2 
        배송부 
     
    
        133 
              Jason Mallin 
        3 
        배송부 
     
    
        134 
              Michael Rogers 
        3 
        배송부 
     
    
        135 
              Ki Gee 
        3 
        배송부 
     
    
        136 
              Hazel Philtanker 
        3 
        배송부 
     
    
        188 
              Kelly Chung 
        3 
        배송부 
     
    
        189 
              Jennifer Dilly 
        3 
        배송부 
     
    
        190 
              Timothy Gates 
        3 
        배송부 
     
    
        191 
              Randall Perkins 
        3 
        배송부 
     
    
        123 
           Shanta Vollman 
        2 
        배송부 
     
    
        137 
              Renske Ladwig 
        3 
        배송부 
     
    
        138 
              Stephen Stiles 
        3 
        배송부 
     
    
        139 
              John Seo 
        3 
        배송부 
     
    
        140 
              Joshua Patel 
        3 
        배송부 
     
    
        192 
              Sarah Bell 
        3 
        배송부 
     
    
        193 
              Britney Everett 
        3 
        배송부 
     
    
        194 
              Samuel McCain 
        3 
        배송부 
     
    
        195 
              Vance Jones 
        3 
        배송부 
     
    
        124 
           Kevin Mourgos 
        2 
        배송부 
     
    
        141 
              Trenna Rajs 
        3 
        배송부 
     
    
        142 
              Curtis Davies 
        3 
        배송부 
     
    
        143 
              Randall Matos 
        3 
        배송부 
     
    
        144 
              Peter Vargas 
        3 
        배송부 
     
    
        196 
              Alana Walsh 
        3 
        배송부 
     
    
        197 
              Kevin Feeney 
        3 
        배송부 
     
    
        198 
              Donald OConnell 
        3 
        배송부 
     
    
        199 
              Douglas Grant 
        3 
        배송부 
     
    
        145 
           John Russell 
        2 
        영업부 
     
    
        150 
              Peter Tucker 
        3 
        영업부 
     
    
        151 
              David Bernstein 
        3 
        영업부 
     
    
        152 
              Peter Hall 
        3 
        영업부 
     
    
        153 
              Christopher Olsen 
        3 
        영업부 
     
    
        154 
              Nanette Cambrault 
        3 
        영업부 
     
    
        155 
              Oliver Tuvault 
        3 
        영업부 
     
    
        146 
           Karen Partners 
        2 
        영업부 
     
    
        156 
              Janette King 
        3 
        영업부 
     
    
        157 
              Patrick Sully 
        3 
        영업부 
     
    
        158 
              Allan McEwen 
        3 
        영업부 
     
    
        159 
              Lindsey Smith 
        3 
        영업부 
     
    
        160 
              Louise Doran 
        3 
        영업부 
     
    
        161 
              Sarath Sewall 
        3 
        영업부 
     
    
        147 
           Alberto Errazuriz 
        2 
        영업부 
     
    
        162 
              Clara Vishney 
        3 
        영업부 
     
    
        163 
              Danielle Greene 
        3 
        영업부 
     
    
        164 
              Mattea Marvins 
        3 
        영업부 
     
    
        165 
              David Lee 
        3 
        영업부 
     
    
        166 
              Sundar Ande 
        3 
        영업부 
     
    
        167 
              Amit Banda 
        3 
        영업부 
     
    
        148 
           Gerald Cambrault 
        2 
        영업부 
     
    
        168 
              Lisa Ozer 
        3 
        영업부 
     
    
        169 
              Harrison Bloom 
        3 
        영업부 
     
    
        170 
              Tayler Fox 
        3 
        영업부 
     
    
        171 
              William Smith 
        3 
        영업부 
     
    
        172 
              Elizabeth Bates 
        3 
        영업부 
     
    
        173 
              Sundita Kumar 
        3 
        영업부 
     
    
        149 
           Eleni Zlotkey 
        2 
        영업부 
     
    
        174 
              Ellen Abel 
        3 
        영업부 
     
    
        175 
              Alyssa Hutton 
        3 
        영업부 
     
    
        176 
              Jonathon Taylor 
        3 
        영업부 
     
    
        177 
              Jack Livingston 
        3 
        영업부 
     
    
        179 
              Charles Johnson 
        3 
        영업부 
     
    
        201 
           Michael Hartstein 
        2 
        마케팅 
     
    
        202 
              Pat Fay 
        3 
        마케팅 
     
CONNECT BY ~ AND : AND를 통해 추가로 조건을 붙인다. 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 % % sql SELECT      a.employee_id     , LPAD(' ' , 3  *  (LEVEL -  1 )) ||  a.emp_name     , LEVEL     , b.department_name FROM     employees a     , departments b WHERE  a.department_id =  b.department_idSTART  WITH  a.manager_id IS  NULL CONNECT  BY  PRIOR a.employee_id =  a.manager_id    AND  a.department_id =  30  
 
 * oracle://ora_user:***@127.0.0.1:1521/myoracle
0 rows affected.
 
    
        employee_id 
        LPAD('',3*(LEVEL-1))||A.EMP_NAME 
        LEVEL 
        department_name 
     
    
        100 
        Steven King 
        1 
        기획부 
     
    
        114 
           Den Raphaely 
        2 
        구매/생산부 
     
    
        115 
              Alexander Khoo 
        3 
        구매/생산부 
     
    
        116 
              Shelli Baida 
        3 
        구매/생산부 
     
    
        117 
              Sigal Tobias 
        3 
        구매/생산부 
     
    
        118 
              Guy Himuro 
        3 
        구매/생산부 
     
    
        119 
              Karen Colmenares 
        3 
        구매/생산부 
     
CONNECT BY PRIOR 자식컬럼 = 부모컬럼 : 부모에서 자식으로 트리 구성 (TOP DOWN) -> 일반적인 구조 
CONNECT BY PRIOR 부모컬럼 = 자식컬럼 : 자식에서 부모로 트리 구성 (Bottom UP) 
CONNECT BY NOCYCLE PRIOR = 무한루프 방지- p.226 WITH 절 
kor_loan_status 테이블에서 연도별 최종월 기준 가장 대출이 많은 도시와 잔액을 구한다. 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 % % sql SELECT  b2.* FROM  ( SELECT  period , region, sum (loan_jan_amt) jan_amt         FROM  kor_loan_status           GROUP  BY  period , region       ) b2,             ( SELECT  b.period,  MAX (b.jan_amt) max_jan_amt          FROM  ( SELECT  period , region, sum (loan_jan_amt) jan_amt                   FROM  kor_loan_status                   GROUP  BY  period , region               ) b,               ( SELECT  MAX (PERIOD ) max_month                   FROM  kor_loan_status                  GROUP  BY  SUBSTR(PERIOD , 1 , 4 )               ) a          WHERE  b.period =  a.max_month          GROUP  BY  b.period       ) c     WHERE  b2.period =  c.period    AND  b2.jan_amt =  c.max_jan_amt  ORDER  BY  1  
 
 * oracle://ora_user:***@127.0.0.1:1521/myoracle
0 rows affected.
 
    
        period 
        region 
        jan_amt 
     
    
        201112 
        서울 
        334728.3 
     
    
        201212 
        서울 
        331572.3 
     
    
        201311 
        서울 
        334062.7 
     
1 - WITH 절은 별칭으로 사용한 SELECT 문의 FROM 절에 다른 SELECT 구문의 별칭 참조가 가능하다. 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 % % sql WITH  b2 AS  (SELECT  period , region, sum (loan_jan_amt) jan_amt         FROM  kor_loan_status           GROUP  BY  period , region)      , c AS  (SELECT  b.period, MAX (b.jan_amt) max_jan_amt              FROM  (SELECT  period , region, sum (loan_jan_amt) jan_amt                  FROM  kor_loan_status                   GROUP  BY  period , region) b                  , (SELECT  MAX (PERIOD ) max_month                     FROM  kor_loan_status                     GROUP  BY  SUBSTR(PERIOD , 1 , 4 )                  ) a              WHERE  b.period =  a.max_month              GROUP  BY  b.period            )  SELECT  b2.* FROM  b2, cWHERE  b2.period =  c.period    AND  b2.jan_amt =  c.max_jan_amt ORDER  BY  1 
 
 * oracle://ora_user:***@127.0.0.1:1521/myoracle
0 rows affected.
 
    
        period 
        region 
        jan_amt 
     
    
        201112 
        서울 
        334728.3 
     
    
        201212 
        서울 
        331572.3 
     
    
        201311 
        서울 
        334062.7 
     
Reference : 오라클 SQL과 PL/SQK을 다루는 기술