10g / 11gでは、これにモデル句を使用できます。
SQL> with emps as (select rownum id, name, start_date,
2 end_date, trunc(end_date)-trunc(start_date) date_range
3 from table1)
4 select name, the_date
5 from emps
6 model partition by(id as key)
7 dimension by(0 as f)
8 measures(name, start_date, cast(null as date) the_date, date_range)
9 rules (the_date [for f from 0 to date_range[0] increment 1] = start_date[0] + cv(f),
10 name[any] = name[0]);
NAME THE_DATE
----------- ----------
DAVID SMITH 01-01-2001
DAVID SMITH 01-02-2001
DAVID SMITH 01-03-2001
DAVID SMITH 01-04-2001
DAVID SMITH 01-05-2001
DAVID SMITH 01-06-2001
JOHN SMITH 02-07-2012
JOHN SMITH 02-08-2012
JOHN SMITH 02-09-2012
9 rows selected.
つまり、基本クエリ:
select rownum id, name, start_date,
end_date, trunc(end_date)-trunc(start_date) date_range
from table1
日付と範囲を定義するだけです(私はrownum idを使用しましたが、PKがある場合は、代わりにそれを使用できます。
パーティションは、ID(一意の行)ごとに計算を分割します。
6 model partition by(id as key)
対策:
8 measures(name, start_date, cast(null as date) the_date, date_range)
出力/計算する属性を定義します。この場合、name、start_date、および生成する行の範囲を使用しています。さらに、計算された日付を保持する列the_date
を定義しました(つまり、start_date + nを計算します。ここで、nは0から範囲です。
ルールは、列に入力する方法を定義します。
9 rules (the_date [for f from 0 to date_range[0] increment 1] = start_date[0] + cv(f),
10 name[any] = name[0]);
だから
the_date [for f from 0 to date_range[0] increment 1]
date_rangeが保持する行数+1(つまり、合計6つの日付)を生成すると言っています。の値は、 (現在の値)関数f
を介して参照できます。cv
したがって、davidの1行目にはがthe_date [0] = start_date+0
あり、続いて2行目にはがありthe_date [1] = start_date+1
ます。start_date + 5までのすべての方法(つまりend_date
)
接続するためのpsは、次のようなことを行う必要があります。
select
A.EMPLOYEE_NAME,
A.START_DATE+(b.r-1) AS INDIVIDUAL_DAY,
TO_CHAR(A.START_DATE,'MM/DD/YYYY') START_DATE,
TO_CHAR(A.END_DATE,'MM/DD/YYYY') END_DATE
FROM table1 A
cross join (select rownum r
from (select max(end_date-start_date) d from table1)
connect by level-1 <= d) b
where A.START_DATE+(b.r-1) <= A.END_DATE
order by 1, 2;
つまり、サブクエリへの接続を分離してから、individual_day>end_dateの行を除外します。
しかし、私はこのアプローチをお勧めしません。そのパフォーマンスは、モデルアプローチと比較して悪化します(特に範囲が大きくなる場合)。