Beziehung über mehrere Entitäten?

akretschmer

Datenbank-Guru
Beiträge
9.028
mal so als Fingerübung...

Code:
edb=*# select * from kinder ;
 name  |      geb_datum      
-------+---------------------
 max   | 2014-02-01 00:00:00
 susi  | 2015-02-01 00:00:00
 tilo  | 2016-02-01 00:00:00
 elli  | 2017-02-01 00:00:00
 sarah | 2018-02-01 00:00:00
 fritz | 2019-02-01 00:00:00
(6 rows)

edb=*# select *, age(geb_datum) from kinder ;
 name  |      geb_datum      |          age           
-------+---------------------+------------------------
 max   | 2014-02-01 00:00:00 | 7 years 9 mons 18 days
 susi  | 2015-02-01 00:00:00 | 6 years 9 mons 18 days
 tilo  | 2016-02-01 00:00:00 | 5 years 9 mons 18 days
 elli  | 2017-02-01 00:00:00 | 4 years 9 mons 18 days
 sarah | 2018-02-01 00:00:00 | 3 years 9 mons 18 days
 fritz | 2019-02-01 00:00:00 | 2 years 9 mons 18 days
(6 rows)

edb=*# select *, extract(year from age(geb_datum)) as alter from kinder ;
 name  |      geb_datum      | alter 
-------+---------------------+-------
 max   | 2014-02-01 00:00:00 |     7
 susi  | 2015-02-01 00:00:00 |     6
 tilo  | 2016-02-01 00:00:00 |     5
 elli  | 2017-02-01 00:00:00 |     4
 sarah | 2018-02-01 00:00:00 |     3
 fritz | 2019-02-01 00:00:00 |     2
(6 rows)
edb=*# with x as (select *, extract(year from age(geb_datum)) as alter from kinder) select case when alter between 1 and 4 then 'bis 4' else 'über 4' end as gruppe, string_agg(name,', ') from x group by 1;
 gruppe |     string_agg     
--------+--------------------
 bis 4  | elli, sarah, fritz
 über 4 | max, susi, tilo
(2 rows)

Du erkennst den Weg?
 
Werbung:

kolom

Benutzer
Beiträge
21
Bislang ist das für mich noch nachvollziehbar :) Nun braucht es das Austrittsdatum 6 Jahre und der darauffolgende 31.07. - da bin ich überfragt
 

dabadepdu

Datenbank-Guru
Beiträge
572
Du könntest eine Tabelle mit den Austrittsdaten anlegen. Im einfachsten Fall eine allgemeine Liste mit ID und Austrittdatum für die kommenden Jahre. Dagegen kannst Du das Geburtsdatum der Kinder plus 6 Jahre rechnen (man kann mit Datumsen rechnen) und das nächst größere Austrittsdatum nehmen.
Jetzt könnte man einwänden, dass es auch ohene Tabelle zu berechnen ist, aber falls Dein Austrittsdatum nicht statisch ist, sondern abhängig vom Bundesland oder den neuestenÖTV Tarifen, wird die Rechnung unübersichtlich.
Dann könnte man bequem verschiedene Austrittsdaten kategorisiert nach Bundesland whatever eintragen (Tabellenerweiterung um die entsprechenden Kriterien und Datenpflege natürlich hinzugenommen plus die Zuordnung des Bundeslandes je Kita).
 

kolom

Benutzer
Beiträge
21
Ich grübel noch ein wenig darüber wie ich es am besten haben möchte, allerdings fehlt mir noch ein bisschen das Verständnis wie ich die Bedingung "31.07. nach 6 Jahre" umsetzen soll.


Ich möchte mir aus der Tabelle Kind zu dem Geburtsdatum das Datum anzeigen lassen, welches der 31.07. nach dem 6. Geburtstag ist.

Code:
SELECT name, vorname, geburtsdatum,

CASE WHEN DATEADD(YEAR, DATEDIFF(YEAR, geburtsdatum, GETDATE()), geburtsdatum) > GETDATE()

THEN DATEDIFF(YEAR, geburtsdatum, GETDATE()) - 1

ELSE DATEDIFF(YEAR, geburtsdatum, GETDATE()) END AS "Alter"

FROM Kind

Diese Abfrage mache ich in einen weiteren CASE rein

WHEN (Alter) > 6
THEN (...)

Ja - was kommt da rein bei THEN damit der darauffolgende 31.07. kommt?

Bsp. wenn das Kind am 21.11.2021 geboren ist, müsste dort herauskommen 31.07.2028 (wird erst im November 2027 6 Jahre alt, also muss entsprechend der 31.07. aus dem nächsten Jahr genommen werden).
 

dabadepdu

Datenbank-Guru
Beiträge
572
Die Ausgangsfrage ist falsch, daher bringt es nichts, sie zu beantworten. Es spielt keine Rolle, ob das Alter > 6 ist. Du musst das Geburtsdatum plus 6 Jahre irgendwie weiterverarbeiten in Bezug auf den Stichtag, so hast Du es zumindest selbst als Problem geschildert.
Wie sähe das Verfahren aus, wenn Du es mit Deinen eigenen Worten beschreibst?
 

kolom

Benutzer
Beiträge
21
Stimmt, das Datum wird ja für alle berechnet, also ist die Bedingung egal.

Mit eigenen Worten wäre es etwa

Wenn Tag+Monat von Geburtsdatum <= 31.07.%, dann 31.07.Jahr von Geburtsdatum + 6 Jahre
Wenn Tag+Monat von Geburtsdatum > 31.07.%, dann 31.07.Jahr von Geburtsdatum + 7 Jahre

Das wäre der Weg den ich gegangen wäre. Das Jahr kann ich mit DATEADD addieren, nur wie gebe sieht die Abfrage aus, dass es für jedes Geburtsdatum funktioniert, und wie sieht die Ausgabe aus, dass nur davon nur die addierte Jahreszahl genommen wird und dem "31.07." hinten dran gestellt?
 

dabadepdu

Datenbank-Guru
Beiträge
572
Grundsätzlich kann SQL nur mit "harten Fakten" arbeiten, vor allem eben das Wichtigste, Vergleiche durchführen. Das ist an anderer Stelle viel häufiger ein Problem, hier ein sagen wir etwas gemeines, was mit dem Datentyp Date und der hier vorliegenden Unvollständigkeit (Jahr fehlt) zusammenhängt.
Aus dem vorigen folgt, dass Du dieses fehlende Jahr selbst bestimmen bzw. angeben musst, um funktionierende Abfragen zu erhalten. Also, berechne, Geburt plus 6 Jahre, extrahiere das Jahr, konkateniere es mit dem 31.7, wandle es wieder in ein Datum und schon bist Du startklar.

Deine formulierte Bedingung würde ich etwas umformulieren:
Wenn Geburtsdatum > 31.07.<JahrDesGeburtsdatums> dann..
sonst ..
Ob Du dabei die Addition der 6 Jahre direkt mit einbeziehst oder nicht, spielt keine Rolle. Ausnahme wäre m.E. ein Stichtag am 29.2.%%%%.
 

dabadepdu

Datenbank-Guru
Beiträge
572
Mir ist noch eingefallen, für den Vergleich größer/kleiner Stichtag reicht auch Monat und Tag.
Wenn man die Vergleichsdaten beide als String formatiert, Format MMDD benötigt man in diesem Fall gar kein Jahr und kann die Fallunterscheidung ohne die Jahresberechnung machen.

Wie so oft, viele Wege führen nach Rom.
 

kolom

Benutzer
Beiträge
21
Ok - ich glaube das funktioniert. Vielen Dank!

Habe es nun mit folgender Abfrage gelöst

Code:
SELECT name, vorname, Geburtsdatum,
CASE
WHEN Geburtsdatum < Convert(DATE,CONCAT('31.07.', YEAR(Geburtsdatum)))
THEN Convert(DATE,CONCAT('31.07.', YEAR(DATEADD(yy, 6, Geburtsdatum))))
WHEN Geburtsdatum > Convert(DATE,CONCAT('31.07.', YEAR(Geburtsdatum)))
THEN Convert(DATE,CONCAT('31.07.', YEAR(DATEADD(yy, 7, Geburtsdatum))))
END
AS Austrittsdatum,
CASE

WHEN Geburtsdatum > Convert(DATE,CONCAT('31.07.', YEAR(Geburtsdatum)))
THEN 'X'

END AS 'Kannkind'
FROM Kind

Muss es nachher nochmal ordentlich durchschauen, sind mir aktuell zu viele Zahlen für diese Uhrzeit😄Aber ich denke das sollte so passen. Vielen, vielen Dank!
 

dabadepdu

Datenbank-Guru
Beiträge
572
Mit > < Operatoren musst Du darauf achten, dass keine Lücken entstehen, hier würde schon nach dem ersten WHEN ein ELSE reichen.
Und Stand jetzt hast Du 3x eine Konstante "31.07" im einem Select. Bei einem View kann man noch sagen, meinetwegen. Aber ich habe den Verdacht, dieser Stichtag wird noch öfter gebracht. (Ich erinnere an meinen Tabellenvorschlag)

Idee:
[/code]
Select .. austritt.stichtag ..
..
..
from kind, (select '31.07.' as stichtag ) austritt[/code]
 
Werbung:
Oben