In der Ausgabe 03/2013 der ORDIX® news [1] hatten wir nach einem Algorithmus gesucht, der alle Personen anzeigt, die heute oder in den nächsten sechs Tagen Geburtstag haben.

Hier die Lösungswege:

01.01.1970: Martin
29.02.1980: Kevin
31.12.1966: Bärbel
01.07.1952: Theo

Abb. 1: Liste der Geburtstagskinder.


 

CREATE OR REPLACE FUNCTION fnc_next_birthday
( pi_geb   DATE
, pi_heute DATE DEFAULT SYSDATE )
RETURN DATE
IS
  v_next_birthday DATE;
  FUNCTION fnc_normalize( pi_ddmm CHAR, pi_yyyy CHAR )
  RETURN DATE
  IS
    e1839_date_not_valid EXCEPTION;
    PRAGMA EXCEPTION_INIT( e1839_date_not_valid, -1839 );
    v_ret DATE;
  BEGIN
    v_ret := to_date( pi_ddmm || pi_yyyy, 'DDMMYYYY' );
    RETURN v_ret;
  EXCEPTION
    WHEN e1839_date_not_valid THEN
     IF( pi_ddmm = '2902' )THEN
       v_ret := to_date( '2802' || pi_yyyy , 'DDMMYYYY');
       RETURN v_ret;
     ELSE
       RAISE;
     END IF;
END;
BEGIN
v_next_birthday := fnc_normalize( to_char( pi_geb, 'DDMM' ), to_char( pi_heute, 'YYYY' ) );
IF( v_next_birthday >= pi_heute ) THEN
   RETURN v_next_birthday;
END IF;
v_next_birthday := fnc_normalize( to_char( pi_geb, 'DDMM' ), to_char( pi_heute+365, 'YYYY' ));
RETURN v_next_birthday;
END;
/

Abb. 2: Funktion zur Ermittlung des nächsten Geburtstags (Lösung 1).


WITH param AS (
       SELECT to_date( '23.02.2013', 'DD.MM.YYYY' ) AS heute
       ,     6 AS anzahl_tage_nachher
       FROM   dual
     )
,   tage AS (
       SELECT heute + ( level - 1 ) AS tag
       FROM   param CONNECT BY LEVEL <= anzahl_tage_nachher + 1
   )
,   tage_mit_29 AS(
       SELECT to_char( tag, 'MMDD' ) AS tag_mmdd
      FROM   tage
       UNION
       -- In NICHT-Schaltjahren, den 29.02 hinzufuegen
       -- wenn der 28.02 enthalten ist
       SELECT '0229' AS tag_mmdd
       FROM   dual
       WHERE '0228' IN ( SELECT to_char( tag, 'MMDD' ) FROM tage )
       AND  '0229' != ( SELECT to_char( tag + 1, 'MMDD' )
                           FROM   tage
                          WHERE '0228' = to_char( tag, 'MMDD' )
                         )
   )
SELECT   *
FROM     tage_mit_29
ORDER BY 1;.

Abb. 3: Generierung einer MMDD-Liste (Lösung 2).


 

CREATE OR REPLACE FUNCTION fnc_schaltjahre( pi_year NUMBER )
RETURN NUMBER
IS
BEGIN
RETURN floor(( pi_year ) / 4 ) - floor(( pi_year ) / 100) + floor(( pi_year ) / 400 );
END fnc_schaltjahre;
/

Abb. 4: Anzahl der Schalttage zu einem Jahr (Lösung 3).

Logo ORDIX<sup>®</sup>  news lang