sql >> Database teknologi >  >> RDS >> Oracle

Sådan genereres rækker for datointerval efter nøgle

i 10g/11g kan du bruge modelklausulen til dette.

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.

dvs. din basisforespørgsel:

select rownum id, name, start_date,
       end_date, trunc(end_date)-trunc(start_date) date_range
  from table1

definerer bare datoerne + intervallet (jeg brugte rownum id, men hvis du har en PK, kan du bruge det i stedet.

partitionen opdeler vores beregninger pr. ID (unik række):

6  model partition by(id as key)

foranstaltningerne:

8        measures(name, start_date, cast(null as date) the_date, date_range)

definerer de attributter, vi vil udskrive/beregne. i dette tilfælde arbejder vi med navn og startdatoen plus rækken af ​​rækker, der skal genereres. Derudover har jeg defineret en kolonne the_date der vil holde den beregnede dato (dvs. vi ønsker at beregne startdato + n hvor n er fra 0 til intervallet.

reglerne definerer HVORDAN vi skal udfylde vores kolonner:

9        rules (the_date [for f from 0 to date_range[0] increment 1]  = start_date[0] + cv(f),
10               name[any] = name[0]);

så med 

the_date [for f from 0 to date_range[0] increment 1]

vi siger, at vi vil generere det antal rækker, som date_range indeholder+1 (dvs. 6 datoer i alt). værdien af ​​f kan refereres gennem cv (aktuel værdi) funktion.

så på række 1 for david ville vi have the_date [0] = start_date+0 og efterfølgende på række 2 ville vi have the_date [1] = start_date+1 . helt op til start_date+5 (dvs. end_date )

p.s. for at oprette forbindelse skal du gøre noget som dette:

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;

dvs. isoler forbindelsen til en underforespørgsel, og filtrer derefter rækkerne fra, hvor individual_day> end_date.

men jeg VIL IKKE anbefale denne tilgang. dens ydeevne vil være dårligere sammenlignet med modeltilgangen (især hvis intervallerne bliver store).



  1. MySQL Administrator Backups:Kompatibilitetstilstand, hvad gør dette præcist?

  2. MySQL ::Vælg fra kommasepareret streng

  3. Hvad returnerer Java MySQL executeUpdate() for INSERT ON ON DUPLICATE KEY UPDATE?

  4. MySQL:Sum værdier i underforespørgsler