13. April 2007

Die Tage "zwischen" zwei Datumswerten ... ganz einfach ...

Wenn man mit Datumswerten zu tun hat, muss man häufig alle Tage zwischen einem Beginn-Datum und einem Ende-Datum ermitteln. Wie macht man dies am einfachsten ...? Nichts leichter als das:
BEZEICHNUNG                    START_DATU END_DATUM
------------------------------ ---------- ----------
Veranstaltung 1                01.05.2007 10.05.2007
Veranstaltung 2                16.05.2007 19.05.2007
Veranstaltung 3                07.07.2007 12.07.2007
Zuerst lege man sich eine Hilfstabelle mit allen Datumswerten wie folgt an:
create table datum (
  datum date,
  constraint pk_datum primary key (datum)
) organization index
/

declare
  v_curr_date date := to_date('2005-01-01', 'YYYY-MM-DD');
  v_end_date  date := to_date('2015-01-01', 'YYYY-MM-DD');
begin
  while v_curr_date < v_end_date loop
    insert into datum values (v_curr_date);
    v_curr_date := v_curr_date + 1;
  end loop;
end;
/
sho err

commit
/
Um den Zugriff auf die Hilfstabelle zu optimieren, wählen wir eine index-organized-table. Nun lassen sich die Tage zwischen Beginn- und Ende-Datum einfach durch einen Join ermitteln:
select v.bezeichnung, d.datum
from veranstaltung v join datum d on (d.datum between v.start_datum and v.end_datum)
/

BEZEICHNUNG                    DATUM
------------------------------ ----------
Veranstaltung 1                01.05.2007
Veranstaltung 1                02.05.2007
Veranstaltung 1                03.05.2007
Veranstaltung 1                04.05.2007
Veranstaltung 1                05.05.2007
Veranstaltung 1                06.05.2007
Veranstaltung 1                07.05.2007
Veranstaltung 1                08.05.2007
Veranstaltung 1                09.05.2007
Veranstaltung 1                10.05.2007

Veranstaltung 2                16.05.2007
Veranstaltung 2                17.05.2007
Veranstaltung 2                18.05.2007
Veranstaltung 2                19.05.2007

Veranstaltung 3                07.07.2007
Veranstaltung 3                08.07.2007
Veranstaltung 3                09.07.2007
Veranstaltung 3                10.07.2007
Veranstaltung 3                11.07.2007
Veranstaltung 3                12.07.2007
Natürlich können auch die Wochenenden ausgefiltert werden:
select v.bezeichnung, d.datum
from test v join datum d on (
  d.datum between v.start_datum and v.end_datum 
  and rtrim(to_char(d.datum, 'DAY', 'nls_date_language=''GERMAN''')) not in ('SAMSTAG','SONNTAG')
)
/

BEZEICHNUNG                    DATUM
------------------------------ ----------
Veranstaltung 1                01.05.2007
Veranstaltung 1                02.05.2007
Veranstaltung 1                03.05.2007
Veranstaltung 1                04.05.2007
Veranstaltung 1                07.05.2007
Veranstaltung 1                08.05.2007
:

1 Kommentar:

Axel Halkow hat gesagt…

Nur für die Ermittlung der Anzahl der Tage reicht auch ein:

SELECT TO_DATE ('2015-01-01', 'YYYY-MM-DD')
- TO_DATE ('2005-01-01', 'YYYY-MM-DD') AS anzahl
FROM DUAL;

Beliebte Postings