Using the Model Clause to Extend Dates

advertisements

I have several different types of data involving date range that I want to merge together, but at the same time broken down by day. So a 3 day piece of data would result in three rows:

start    primary_key
start+1  primary_key
start+2  primary_key

I've been playing around using the model clause of the select statement in 10g and was looking for the best way to achieve this. Currently I'm joining a range of dates that covers the full range of possible dates (select min(start date), max(end date)). I'd prefer to be selecting the data and adding in more rows to transform it to a per day dataset.

edit:

I've managed to come up with (now includes sample data):

    SELECT * FROM (
        SELECT 123 req_code,
               345 req_par_code,
               TO_DATE('01-03-2010', 'dd-mm-yyyy') req_start_date,
               TO_DATE('05-03-2010', 'dd-mm-yyyy') req_end_date
        FROM dual
)

    MODEL
        PARTITION BY (req_code)
        DIMENSION BY (0 d)
        MEASURES     (SYSDATE dt, req_par_code, req_start_date, req_end_date)
        RULES ITERATE(365) UNTIL (dt[iteration_number] >= TRUNC(req_end_date[0])) (
            dt[iteration_number] = NVL(dt[iteration_number-1] + 1, TRUNC(req_start_date[0])),

            --Copy data across
            req_par_code[ iteration_number ] = req_par_code[0],
            req_start_date[ iteration_number ] = req_start_date[0],
            req_end_date[ iteration_number ] = req_end_date[0]
        )
    ORDER BY dt, req_code;


you can use the MODEL clause to generate rows, here's a small example:

SQL> SELECT * FROM t_data;

        PK START_DATE  END_DATE
---------- ----------- -----------
         1 20/01/2010  20/01/2010
         2 21/01/2010  23/01/2010
         3 24/01/2010  27/01/2010

SQL> SELECT pk, start_date, end_date FROM t_data
  2  MODEL
  3     PARTITION BY (pk)
  4     DIMENSION BY (0 AS i)
  5     MEASURES(start_date, end_date)
  6     RULES
  7     (  start_date[FOR i
  8                   FROM 1 TO end_date[0]-start_date[0]
  9                   INCREMENT 1] = start_date[0] + cv(i),
 10        end_date[ANY] = start_date[CV()] + 1
 11     )
 12  ORDER BY 1,2;

        PK START_DATE  END_DATE
---------- ----------- -----------
         1 20/01/2010  21/01/2010
         2 21/01/2010  22/01/2010
         2 22/01/2010  23/01/2010
         2 23/01/2010  24/01/2010
         3 24/01/2010  25/01/2010
         3 25/01/2010  26/01/2010
         3 26/01/2010  27/01/2010
         3 27/01/2010  28/01/2010