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)
出力/計算する属性を定義します。この場合、名前、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
)
p.s.接続するには、次のような操作を行う必要があります:
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である行を除外します。
しかし、私はこのアプローチをお勧めしません。モデルアプローチと比較してパフォーマンスが低下します(特に範囲が大きくなる場合)。