drop table Ϻǰŷ;

create table Ϻǰŷ
as
select 'A' || lpad(b.no, 4, '0') ǰȣ, a.ŷ, round(dbms_random.value(1, 100)) ŷ
from (select to_char(sysdate - rownum, 'yyyymmdd') ŷ
      from   dual
      connect by level <= 3653) a
    ,(select rownum no from dual connect by level <= 100) b
;

-- ǰ ѰŷǼ Ȯ 
select count(distinct ǰȣ) ǰ, count(*)
from   Ϻǰŷ;

-- ǰ ŷǼ Ȯ 
select avg(cnt)
from  (select ǰȣ, count(*) cnt
       from   Ϻǰŷ
       group by ǰȣ);


drop table ǰ̷;

create table ǰ̷
as
select ǰȣ
     ,(case when ŷ = min(ŷ) over (partition by ǰȣ) then ּ else ŷ end) 
     ,(case when ŷ = max(ŷ) over (partition by ǰȣ) then '99991231' else to_char(to_date(ŷ, 'yyyymmdd') + 3, 'yyyymmdd') end) 
     , round(dbms_random.value(100, 10000), -2) ǸŰ
from (
    select ǰȣ, ŷ, mod(rownum, 4) no
    from (
        select ǰȣ, ŷ
        from   Ϻǰŷ
        order by ǰȣ, ŷ
    )
), (select min(ŷ) ּ from Ϻǰŷ)
where  no = 1
;

-- ǰ ̷°Ǽ Ȯ 
select ǰȣ, min(), max(), count(*)
from   ǰ̷
group by ǰȣ
order by 1, 2
;

-- ̷°Ǽ Ȯ 
select avg(cnt)
from (
  select ǰȣ, count(*) cnt
  from   ǰ̷
  group by ǰȣ
)
;

-- ε  
create index ǰ̷_idx on ǰ̷(ǰȣ, , );

--  
exec dbms_stats.gather_table_stats(user, 'Ϻǰŷ');
exec dbms_stats.gather_table_stats(user, 'ǰ̷');

-- Ϲ ̷ ȸ (NL  )
select /*+ leading(b) use_nl(a) index(a ǰ̷_idx)*/ 
       sum(b.ŷ) Ѱŷ
     , sum(b.ŷ * a.ǸŰ) Ǹűݾ
     , round(avg(b.ŷ * a.ǸŰ)) Ǹűݾ     
from   ǰ̷ a, Ϻǰŷ b
where  b.ǰȣ = a.ǰȣ
and    b.ŷ between a. and a.
;

-- Ʃ ̷ ȸ (NL   rowid ̿)
-- (, Ʒ  SQL Ʈ̽ ɸ ſ  ɸ ׳ ϸ   ȸ˴ϴ. 
-- 9i, 10g, 11g  Ÿ ̸, ׶ ˴ϴ.)
select /*+ ordered use_nl(b) rowid(b) */
       sum(a.ŷ) Ѱŷ
     , sum(a.ŷ * b.ǸŰ) Ǹűݾ
     , round(avg(a.ŷ * b.ǸŰ)) Ǹűݾ
from   Ϻǰŷ a, ǰ̷ b
where  b.rowid = (select /*+ index_desc(c ǰ̷_idx)*/ rowid
                  from   ǰ̷ c
                  where  ǰȣ = a.ǰȣ
                  and    a.ŷ between c. and c.
                  and    rownum <= 1)
;

-- Ϲ ̷ ȸ (ؽ  )
select /*+ leading(a) use_hash(b) */ 
       sum(b.ŷ) Ѱŷ
     , sum(b.ŷ * a.ǸŰ) Ǹűݾ
     , round(avg(b.ŷ * a.ǸŰ)) Ǹűݾ     
from   ǰ̷ a, Ϻǰŷ b
where  b.ǰȣ = a.ǰȣ
and    b.ŷ between a. and a.
;

drop table ǰ̷2;

create table ǰ̷2
as
select ǰȣ
     ,(case when ŷ = min(ŷ) over (partition by ǰȣ) then ּ else to_char(ŷ, 'yyyymmdd') end) 
     ,(case when ŷ = max(ŷ) over (partition by ǰȣ) then '99991231' else to_char(lead(ŷ) over (partition by ǰȣ order by ŷ)-1, 'yyyymmdd') end) 
     , round(dbms_random.value(100, 10000), -2) ǸŰ
from (
    select ǰȣ, to_date(ŷ, 'yyyymmdd') ŷ, mod(rownum, 4) no
    from (
        select ǰȣ, ŷ
        from   Ϻǰŷ
        order by ǰȣ, ŷ
    )
), (select min(ŷ) ּ from Ϻǰŷ)
where  no = 1 or to_char(ŷ, 'dd') = '01'
;

select /*+ leading(a) use_hash(b) */ 
       sum(b.ŷ) Ѱŷ
     , sum(b.ŷ * a.ǸŰ) Ǹűݾ
     , round(avg(b.ŷ * a.ǸŰ)) Ǹűݾ     
from   ǰ̷2 a, Ϻǰŷ b
where  b.ǰȣ = a.ǰȣ
and    b.ŷ between a. and a.
and    trunc(to_date(b.ŷ, 'yyyymmdd'), 'mm') = trunc(to_date(a., 'yyyymmdd'), 'mm')
;

drop table ;

create table 
as
select to_char(sysdate, 'yyyymm') ؿ,  to_char(trunc(sysdate, 'mm'), 'yyyymmdd') , '99991231'  
from   dual
union all
select to_char(add_months(trunc(sysdate, 'mm'), -rownum), 'yyyymm')
     , to_char(add_months(trunc(sysdate, 'mm'), -rownum), 'yyyymmdd')
     , to_char(add_months(last_day(sysdate), -rownum), 'yyyymmdd')
from   dual
connect by level <= 12*20
;

select * from  order by 1;

select /*+ ordered use_merge(b) use_hash(c) */ 
       sum(c.ŷ) Ѱŷ
     , sum(c.ŷ * b.ǸŰ) Ǹűݾ
     , round(avg(c.ŷ * b.ǸŰ)) Ǹűݾ     
from    a, ǰ̷ b, Ϻǰŷ c
where  b. <= a.
and    b. >= a.
and    c.ǰȣ = b.ǰȣ
and    c.ŷ between b. and b.
and    trunc(to_date(c.ŷ, 'yyyymmdd'), 'mm') = trunc(to_date(a., 'yyyymmdd'), 'mm')
;


