Oracle SQL 분석 함수 first, last, firstvalue、last_value、nth_value

--     
SEAN@sean> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE    11.2.0.4.0      Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

--  
SEAN@sean> create table t
    as
    select 'A' || mod(level, 3) grp, level val, sysdate + level / 24 crt_date
      from dual
    connect by level <= 9;

Table created.

SEAN@sean> col grp for a10;
SEAN@sean> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';

Session altered.

SEAN@sean> select * from t order by grp,crt_date;

GRP               VAL CRT_DATE
---------- ---------- -------------------
A0                  3 2017-07-25 11:13:41
A0                  6 2017-07-25 14:13:41
A0                  9 2017-07-25 17:13:41  --   1
A1                  1 2017-07-25 09:13:41
A1                  4 2017-07-25 12:13:41
A1                  7 2017-07-25 15:13:41  --   2
A2                  2 2017-07-25 10:13:41
A2                  5 2017-07-25 13:13:41
A2                  8 2017-07-25 16:13:41  --   3

9 rows selected.

SEAN@sean> exec dbms_stats.gather_table_stats(user,'T');

PL/SQL procedure successfully completed.

--  
     (crt_date)      (val),        result_val   result_crt_date

--   order by  t.crt_date         ,         。       rowid      order by  t.crt_date,rowid,     order by  t.crt_date        

--  1 row_number()
SEAN@sean> select grp, val result_val, crt_date result_crt_date
      from (select t.grp,
                   t.val,
                   t.crt_date,
                   row_number() over(partition by t.grp order by crt_date desc) rn
              from t)
     where rn = 1;

GRP        RESULT_VAL RESULT_CRT_DATE
---------- ---------- -------------------
A0                  9 2017-07-25 17:13:41
A1                  7 2017-07-25 15:13:41
A2                  8 2017-07-25 16:13:41

--  2 (last + order by asc)
SEAN@sean> select t.grp,
           max(t.val) keep(dense_rank last order by t.crt_date asc) result_val,
           max(t.crt_date) keep(dense_rank last order by t.crt_date asc) result_crt_date
      from t
     group by t.grp;

GRP        RESULT_VAL RESULT_CRT_DATE
---------- ---------- -------------------
A0                  9 2017-07-25 17:13:41
A1                  7 2017-07-25 15:13:41
A2                  8 2017-07-25 16:13:41

--  3 (first + order by desc)
SEAN@sean> select t.grp,
           max(t.val) keep(dense_rank first order by t.crt_date desc) result_val,
           max(t.crt_date) keep(dense_rank first order by t.crt_date desc) result_crt_date
      from t
     group by t.grp;

GRP        RESULT_VAL RESULT_CRT_DATE
---------- ---------- -------------------
A0                  9 2017-07-25 17:13:41
A1                  7 2017-07-25 15:13:41
A2                  8 2017-07-25 16:13:41

--  3.1 (first + order by desc)        ,        
SEAN@sean> select t.grp,t.val,t.crt_date,
           max(t.val) keep(dense_rank first order by t.crt_date desc) over(partition by t.grp) result_val,
           max(t.crt_date) keep(dense_rank first order by t.crt_date desc) over(partition by t.grp) result_crt_date
      from t;

GRP               VAL CRT_DATE            RESULT_VAL RESULT_CRT_DATE
---------- ---------- ------------------- ---------- -------------------
A0                  3 2017-07-25 11:13:41          9 2017-07-25 17:13:41
A0                  9 2017-07-25 17:13:41          9 2017-07-25 17:13:41
A0                  6 2017-07-25 14:13:41          9 2017-07-25 17:13:41
A1                  1 2017-07-25 09:13:41          7 2017-07-25 15:13:41
A1                  7 2017-07-25 15:13:41          7 2017-07-25 15:13:41
A1                  4 2017-07-25 12:13:41          7 2017-07-25 15:13:41
A2                  8 2017-07-25 16:13:41          8 2017-07-25 16:13:41
A2                  2 2017-07-25 10:13:41          8 2017-07-25 16:13:41
A2                  5 2017-07-25 13:13:41          8 2017-07-25 16:13:41

9 rows selected.

--If you omit the windowing_clause entirely, then the default is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
--      ,      ,     RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,          

--  4 (last_value)
select t.grp,t.val,t.crt_date,
       last_value(t.val) over(partition by t.grp order by t.crt_date asc range between unbounded preceding and unbounded following) result_val,
       last_value(t.crt_date) over(partition by t.grp order by t.crt_date asc range between unbounded preceding and unbounded following) result_crt_date
  from t;

--  5 (first_value)
select t.grp,t.val,t.crt_date,
       first_value(t.val) ignore nulls over(partition by t.grp order by t.crt_date desc range between unbounded preceding and unbounded following) result_val,
       first_value(t.crt_date) ignore nulls over(partition by t.grp order by t.crt_date desc range between unbounded preceding and unbounded following) result_crt_date
  from t;
	
--  6 (nth_value)
select t.grp,t.val,t.crt_date, nth_value(t.val, 1)
  from last ignore nulls over(partition by t.grp order by t.crt_date asc rows between unbounded preceding and unbounded following) result_val,
       nth_value(t.crt_date, 1)
  from last ignore nulls over(partition by t.grp order by t.crt_date asc rows between unbounded preceding and unbounded following) result_crt_date
  from t;

  :                       

좋은 웹페이지 즐겨찾기