Oracle - Geburtstage in den nächsten 30 Tagen

marja

Benutzer
Beiträge
7
Hallo zusammen,

ich möchte gerne mit vorhandenen Daten abfragen, welche Geburtstage demnächst anstehen.
Hierfür habe ich eine Tabelle mit den Usern und den Geburtstagen.

Nun möchte ich gerne eine View erstellen in der mir die User angezeigt werden die von heute bis in den nächsten 30 Tagen (also demnächst) Geburtstag haben. Der Geburtstag ist ja bsp. 01.01.1978 abgespeichert. Um zu vergleichen müsste ich doch erst das vorhandene Geburtstag EXTRACT nach Tag, Monat plus aktuelles Jahr und dann mit BETWEEN zwischen dem heutigen Tag (SYSDATE) und dem Tag in 30 Tagen vergleichen?

Wie aber kann ich am beste dieses Geburtstdatum zusammenbauen oder kann ich auch das Datum vergleichen ohne die Jahreszahl?

Dank Marja
 
Werbung:
Lösung für PostgreSQL, könnte evtl. auch direkt in Oracle gehen:

Code:
test=*# select * from marja ;
 person |    geb     
--------+------------
      1 | 1966-08-30
      2 | 1977-02-16
      3 | 2007-03-10
(3 rows)

test=*# select * from marja where extract(year from age( geb, current_date)) != extract(year from age( geb, current_date + 3));
 person | geb
--------+-----
(0 rows)

test=*# select * from marja where extract(year from age( geb, current_date)) != extract(year from age( geb, current_date + 30));
 person |    geb     
--------+------------
      2 | 1977-02-16
(1 row)

test=*# select * from marja where extract(year from age( geb, current_date)) != extract(year from age( geb, current_date + 60));
 person |    geb     
--------+------------
      2 | 1977-02-16
      3 | 2007-03-10
(2 rows)
 
In Oracle kann man sehr schön mit DATE Spalten rechnen. Das hilft hier allerdings nicht so.
Man muss die Jahre loswerden, die in den Geburtstagdatumswerten stecken. Dazu eignet sich schlicht eine Formatierung nach MonatTag MMDD und dieses Verfahren dürfte dann sogar in nahezu jedem Datenbanksystem funktionieren. (Natürlich unterscheiden sich die Datums-Funktionen )

Code:
-- die Geburtstage der nächsten 30 Tage
-- mit bdate = Spalte mit Geburtsdatum
-- und birthdatetable = verwendete Tabelle
-- die select clause dient nur der Anschauung
-- die where clause reicht.
select bdate,                          
       to_char(bdate,   'mmdd') as bday,
       to_char(sysdate, 'mmdd') as today,
       to_char(bdate,   'mmdd') - to_char(sysdate, 'mmdd') as daysBetween
  from birthdateTable  
 where to_char(bdate,   'mmdd') -
       to_char(sysdate, 'mmdd') between 0 and 30
 
Bist Du Dir da sicher?

Code:
test=*# select to_char('2020-03-01'::date,'mmdd')::int - to_char(current_date, 'mmdd')::int;
 ?column?
----------
       91
(1 row)

to_char() liefert das, was der Name suggeriert, und damit ist schon mal schlecht rechnen. Und dann ist 'mmdd' im 'dd' - Teil ja auch auf max. 31 begrenzt. Mir kommt das komisch vor ...
 
oh mann wie peinlich!

Also die Formatmaske ist Schrott, es muss "DDD" sein.



Code:
..where 
to_char(bdate,'DDD')-
to_char(current_date, 'DDD') between 0 and 30
 
Werbung:
Der Ausdruck "to_char(bdate,'DDD') - to_char(current_date, 'DDD')" wird überhaupt nicht funktionieren, da man nicht einen String von einem anderen abziehen kann. Man muss den String den man darüber erhält, wieder in ein richtiges Datum umwandeln, sonst kann man damit nicht rechnen.

Ich würde das so machen:
Code:
with bdays as (
  select name, bday,
         case
           when to_char(sysdate, 'mmdd') <= to_char(bday, 'mmdd')
              then to_date(to_char(extract(year from sysdate), 'FM0000')||to_char(bday, 'mmdd'), 'yyyymmdd')
           else
             to_date(to_char(extract(year from sysdate) + 1, 'FM0000')||to_char(bday, 'mmdd'), 'yyyymmdd')
         end as next_bday
  from the_table
)
select *
from bdays
where next_bday <= sysdate + 30

Die CTE liefert alle Einträge der Tabelle und berechnet für jeden, wann der nächste Geburtstag ansteht.

Der CASE Ausdruck prüft ob der Geburtstag dieses Jahr schon war, dann ist erst nächstes Jahr wieder einer fällig. Wenn nicht, dann eben dieses Jahr. Im äußeren SELECT wird dann nur noch abgeprüft ob in den nächsten 30 Tagen einer ansteht.

Online Beispiel
 
Zurück
Oben