en 10g/11g puede usar la cláusula modelo para esto.
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.
es decir, su consulta base:
select rownum id, name, start_date,
end_date, trunc(end_date)-trunc(start_date) date_range
from table1
solo define las fechas + el rango (utilicé el ID de número de fila, pero si tiene un PK, puede usarlo en su lugar.
la partición divide nuestros cálculos por ID (fila única):
6 model partition by(id as key)
las medidas:
8 measures(name, start_date, cast(null as date) the_date, date_range)
define los atributos que generaremos/calcularemos. en este caso, estamos trabajando con el nombre y la fecha de inicio más el rango de filas para generar. además, he definido una columna the_date
que contendrá la fecha calculada (es decir, queremos calcular start_date + n donde n es desde 0 hasta el rango.
las reglas definen CÓMO vamos a llenar nuestras columnas:
9 rules (the_date [for f from 0 to date_range[0] increment 1] = start_date[0] + cv(f),
10 name[any] = name[0]);
así con
the_date [for f from 0 to date_range[0] increment 1]
estamos diciendo que generaremos el número de filas que contiene date_range+1 (es decir, 6 fechas en total). el valor de f
se puede hacer referencia a través del cv
(valor actual) función.
entonces en la fila 1 para david, tendríamos the_date [0] = start_date+0
y posteriormente en la fila 2, tendríamos the_date [1] = start_date+1
. todo el camino hasta start_date+5 (es decir, el end_date
)
p.s.para conectarse por necesitaría hacer algo como esto:
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;
es decir, aísle la conexión por a una subconsulta, luego filtre las filas donde individual_day> end_date.
pero NO recomendaría este enfoque. su rendimiento será peor en comparación con el enfoque del modelo (especialmente si los rangos aumentan).