in 10g/11g kunt u hiervoor de modelclausule gebruiken.
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.
dwz uw basisquery:
select rownum id, name, start_date,
end_date, trunc(end_date)-trunc(start_date) date_range
from table1
definieert alleen de datums + het bereik (ik gebruikte rijnummer-ID, maar als je een PK hebt, kun je die in plaats daarvan gebruiken.
de partitie splitst onze berekeningen per ID (unieke rij):
6 model partition by(id as key)
de maatregelen:
8 measures(name, start_date, cast(null as date) the_date, date_range)
definieert de attributen die we zullen uitvoeren/berekenen. in dit geval werken we met de naam en de startdatum plus het bereik van de te genereren rijen. daarnaast heb ik een kolom gedefinieerd the_date
die de berekende datum bevat (d.w.z. we willen start_date + n berekenen waarbij n van 0 tot het bereik is.
de regels bepalen HOE we onze kolommen gaan vullen:
9 rules (the_date [for f from 0 to date_range[0] increment 1] = start_date[0] + cv(f),
10 name[any] = name[0]);
dus met
the_date [for f from 0 to date_range[0] increment 1]
we zeggen dat we het aantal rijen zullen genereren dat date_range bevat+1 (dwz 6 datums in totaal). de waarde van f
kan worden verwezen via de cv
(huidige waarde) functie.
dus op rij 1 voor david hebben we the_date [0] = start_date+0
en vervolgens zouden we in rij 2 the_date [1] = start_date+1
. hebben . helemaal tot aan start_date+5 (d.w.z. de end_date
)
p.s. voor verbinding maken door zou je zoiets als dit moeten doen:
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;
d.w.z. isoleer de verbinding door met een subquery en filter vervolgens de rijen uit waar individual_day> end_date.
maar ik zou deze aanpak NIET aanbevelen. de prestaties zullen slechter zijn in vergelijking met de modelbenadering (vooral als het bereik groot wordt).