Vom Tag X zum gleichen Datum in anderem Jahr

Liebe Leut’,

ich denke, das Folgende müsste einfach gehen, ich kriege es bisher aber nur umständlich hin:

Tabelle A enthält ein Datumsfeld, genannt startdatum, die Jahre in startdatum sind nicht für alle Sätze in Tabelle A gleich. Tabelle B enthält ebenfalls ein Datumsfeld, genannt plandatum, außerdem ist sie über den Fremdschlüssel a_idn mit dem Primärschlüssel idn von Tabelle A verknüpft.

Es sollen jetzt neue Sätze für Tabelle B erzeugt werden, in denen Tag und Monat von plandatum gleich Tag und Monat von startdatum im passenden Satz aus Tabelle A sind, das Jahr aber neu und für alle neuen Sätze gleich. Ich kann also kein festes Intervall in Jahren angeben, das zu startdatum addiert werden könnte.

Also: Zu den Sätzen aus A:

idn    startdatum
1      2006-08-01
2      2008-01-31

sollen in B erzeugt werden:

a_idn   plandatum
1        2010-08-01
2        2010-01-31

usw. usf. Ich habe eine funktionierende, in meinen Augen aber hässliche Firebird-Lösung:

neujahr ist als char(4) deklariert, neudatum als date, und es wird so berechnet:

neudatum = CAST((neujahr || '-' || EXTRACT(MONTH FROM startdatum) 
  || '-' || EXTRACT(DAY FROM startdatum)) AS DATE)

Das ist, wenn ich nicht irre, Standard-SQL pur, sollte also auch in PostgreSQL gehen. Aber eine Jahreszahl ist keine Zeichenkette! Und PostgreSQL hat ja mehr Datums- und Zeitfunktionen als Firebird, das nicht einmal INTERVAL kennt. Trotzdem finde ich keine Funktion, die mir erlaubt, ein Datum aus den drei Zahlen Jahr, Monat, Tag zusammenzusetzen, ohne sinnwidrige Umwege über Zeichenketten zu gehen.

Habe ich Tomaten auf den Augen?

Ja.

Du übersiehst schon mal, daß Du ein Schaltjahrproblem hast.

Du könntest folgendes für Dich anpassen (um z.B. ein gegebenes Datum auf 2000 zu mappen):

test=*# select (current_date- n.n * '1year'::interval)::date from (select extract(year from current_date)-2000 as n) as n;
    date
------------
 2000-11-06
(1 row)

current_date kannst Du dann mit Deinen realen Daten ersetzen.

Andreas (aus Paris, auf Magnus seinen Vortrag wartend, der gleich beginnt)

Das kommt davon, wenn man sich kurz fassen möchte. Den Satz hierzu hatte ich vor dem Abschicken gestrichen: “startdatum” ist nicht naturgegeben, das kann ich in Grenzen frei setzen und der 29.2. bietet sich dafür von vornherein nicht an. Und auch die Verschiebung um einen Tag, die sich mit EXTRACT(DOY FROM startdatum) ergeben könnte, wäre unproblematisch. Es handelt sich hier um eine Datenbank für den eigenen Bedarf.

Du könntest folgendes für Dich anpassen (um z.B. ein gegebenes Datum auf 2000 zu mappen):

test=*# select (current_date- n.n * ‘1year’::interval)::date from (select extract(year from current_date)-2000 as n) as n;
date

2000-11-06
(1 row)

>
> current_date kannst Du dann mit Deinen realen Daten ersetzen.

Darüber muss ich noch ein bisschen brüten. Eventuell kommt da noch eine Rückfrage.

Was mir eigentlich vorschweben würde, wäre wohl eher eine Programmiersprachen-Konstruktion, hier mal Python:

```text
startdatum = datetime.date(2006, 11, 7)
neujahr = 2010    #  Oder irgendein passender Ausdruck
neudatum = startdatum.replace(year=neujahr)

Allerdings mit dem gleichen Schaltjahrproblem. Aber schön durchsichtig.

Erst mal besten Dank,
Sibylle



test=*# select regexp_replace(current_date::text,E'^\\d{4}','2000');
 regexp_replace
----------------
 2000-11-07
(1 row)

Andreas

Das gefällt mir, schon wegen der Kürze. Im Moment konnte und kann ich an dieser Sache nicht weitermachen, frühestens zum Wochenende komme ich weiter.

Dank und Gruß,
Sibylle