[Oracle SQL] Fall mit Folgefall

Zureh

Freizeitschrauber(in)
Hallo,

ich habe mir zwei kleine Testtabellen erstellt um ein Problem von mir zu lösen. Leider gelingt mir das nicht. Vielleicht könnt Ihr mir ja weiter helfen.

Also:

Ich habe verschiedene Fälle. Diese Fälle können einen Folgefall haben (Also ein Fall, der nach diesem Fall kommt).

Die ID ist der Primärschlüssel für den Kunden
Aufn = Aufnahmedatum
Entl = Entlassungsdatum
Arzt = Behandelnder Arzt

Ich habe zwei Tabellen, die so aussehen:

Tabelle Faelle:

ID | aufn | entl | arzt
---------------------------------------------
12345 | 01.01.2014 | 01.03.2014 | 1111111111
12345 | 01.03.2014 | 01.06.2014 | 2222222222
12345 | 01.07.2014 | 01.09.2014 | 3333333333

Tabelle Folge-Faelle:

ID | folge_aufn | folge_entl | folge_arzt
---------------------------------------------
12345 | 01.03.2014 | 01.06.2014 | 2222222222
12345 | 01.07.2014 | 01.09.2014 | 3333333333

Nun möchte ich meine Daten aus beiden Tabellen so selektieren, dass ich je den Fall und den Folgefall bekomme. Das Ergebnis soll so aussehen:

ID | aufn | entl | arzt | folge_aufn | folge_entl | folge_arzt
-------------------------------------------------------------------------------------
12345 | 01.01.2014 | 01.03.2014 | 1111111111 | 01.03.2014 | 01.06.2014 | 2222222222
12345 | 01.03.2014 | 01.06.2014 | 2222222222 | 01.03.2014 | 01.06.2014 | 2222222222
12345 | 01.07.2014 | 01.09.2014 | 3333333333 | null | null | null

Mein Problem liegt beim arzt. Ohne die Ärztenummer funktioniert es und es kommt das richtige Ergebnis (Nur halt ohne die Spalten arzt und folge_arzt) raus. Mit den beiden Spalten bekomme ich dieses Ergebnis:
ID | aufn | entl | arzt | folge_aufn | folge_entl | folge_arzt
-------------------------------------------------------------------------------------
12345 | 01.01.2014 | 01.03.2014 | 1111111111 | 01.03.2014 | 01.06.2014 | 2222222222
12345 | 01.01.2014 | 01.03.2014 | 1111111111 | 01.07.2014 | 01.09.2014 | 3333333333 (X)
12345 | 01.03.2014 | 01.06.2014 | 2222222222 | 01.07.2014 | 01.09.2014 | 3333333333
12345 | 01.07.2014 | 01.09.2014 | 3333333333 | null | null | null

Die 2. Zeile (Mit einem (X) markiert) soll hier nicht rein, weil der direkte Folgefall ja am 01.03. und nicht am 01.07. beginnt. Ich komme einfach nicht drauf, wie ich es verknüpfen muss :/

Ich hoffe, ich konnte es verständlich erklären. Weiß jemand, wie ich mein Problem lösen kann? Ich komme hier einfach nicht weiter...
 
Zuletzt bearbeitet:
Sorry, wollte es eigentlich mit posten aber habe es wohl irgendwie vergessen:

SELECT a.ID, a.aufn, a.entl, a.arzt, min(b.folge_aufn) folge_aufn, min(b.folge_entl) folge_entl, b.arzt_folge
FROM faelle a, folge_faelle b
WHERE a.ID = b.ID (+)
and a.entl <= b.folge_aufn (+)
GROUP BY a.ID, a.aufn, a.entl, a.arzt, b.folge_arzt
ORDER BY a.aufn
 
Wenn du dich nicht vertippt hast, muss es erst mal b.folge_arzt anstatt b.arzt_folge heißen.

Bin mir unsicher, ob ich die Anforderungen 100% richtig verstanden habe, aber so müsste es gehen:
Code:
 SELECT a.ID, a.aufn, a.entl, a.arzt, min(b.folge_aufn) folge_aufn, min(b.folge_entl) folge_entl, b.folge_arzt
FROM faelle a, folge_faelle b
WHERE a.ID = b.ID 
and a.entl <= b.folge_aufn 
GROUP BY a.ID, a.aufn, a.entl
ORDER BY a.aufn
 
Ja, hatte mich nur vertippt.

Das funktioniert so nicht, weil a.arzt und b.folge_arzt nicht im Group By sind. Wenn ich die mit rein nehmen, sieht das ergebnis so aus:

12345 | 01.01.2014 | 01.03.2014 | 1111111111 | 01.03.2014 | 01.06.2014 | 2222222222
12345 | 01.01.2014 | 01.03.2014 | 1111111111 | 01.07.2014 | 01.09.2014 | 3333333333
12345 | 01.03.2014 | 01.06.2014 | 2222222222 | 01.07.2014 | 01.09.2014 | 3333333333

Die zweite Zeile ist also immer noch zu viel und jetzt fehlt der 3. Fall (3333333333) ohne Folgefall. Deshalb war ja der Join drin (+), damit auch Fälle, die keinen Folgefall haben, trotzdem aufgelistet werden.

Also angenommen du gehst in dieser Reihenfolge zum Arzt:

[1] - Schnupfen
[2] - Husten
[3] - Fieber

Dann soll es so aufgebaut sein:
Fall [1]: Schupfen; Folgefall [2]: Husten
Fall [2]: Husten; Folgefall [3]: Fieber
Fall [3]: Fieber; Folgefall: Keiner

Die Tabellen wären dann so:
Faelle:
Fall [1]: Schnupfen ...
Fall [2]: Husten
Fall [3]: Fieber

Folgefaelle:
Fall [2]: Husten
Fall [3]: Fieber

Fall [1] ist ja kein Folgefall, weil es vor dem Fall keinen anderen Fall gab. Fall [3] hat keinen Folgefall, weil er der Letzte ist.

Das funktioniert soweit auch alles, aber sobald ich verschiedene Ärzte habe, nimmt er für die Fälle einfach mehrere Folgefälle (falls vorhanden). Ich muss also irgendwie einschränken, dass er nur den ersten Folgefall nimmt, unabhängig von der Arzt-Nummer.
 
Zuletzt bearbeitet:
Verstehe. Mein Oracle ist leider ein bisschen eingerostet. (+) entspricht im Prinzip einem LEFT OUTER JOIN, oder?

Edit: Da ich gerade ein Brett vorm Kopf und wenig Zeit habe und die Lösung nicht unmittelbar sehe, hätte ich folgenden Workaround-Vorschlag: Sofern es für dich gangbar ist, das Datenbanklayout zu ändern, könnte man den Folgefall mit einer ID identifizieren, die in der Fall-Tabelle gespeichert wird und in einer (1:1)-Relation zu einem Feld in folge_faelle steht.

faelle:
ID | aufn | entl | arzt | folge_fall

folge_faelle:
folge_fall | folge_aufn | folge_entl | folge_arzt
 
Zuletzt bearbeitet:
Bin mir jetzt nicht sicher ob es ein LEFT oder RIGHT OUTER JOIN IST, weil ich immer nur diese Abkürzung verwende. Aber es ist für den JOIN, ja. Wenn er in der Folge-Tabelle keine Daten dafür findet, wird trotzdem diese Zeile ins Ergebnis geschrieben. Mit NULL Werten für die Folge-Daten.
 
hmm, ich hab grad noch paar verständnis probs ^^ immerhin ein bsp :) bei dem bsp frage ich mich, ob die ganze struktur überhaupt sinnvoll ist. kleine erklärung: du trennst explizit fall von folgefall, aber ein folge-folge-fall ist dann das gleiche wie ein folge-fall? das klingt... merkwürdig ^^

was spräche prinzipiell erstmal dagegen, das alles in einer tabelle zu behandeln? aufbau in etwa so:
Tabelle: Fälle
ID|Patient|Arzt|Aufnahme|Entlassung|Folge
...
3|12345|1|01.01.2014|01.03.2014|4
4|12345|2|01.03.2014|01.06.2014|5
5|12345|3|01.07.2014|01.09.2014|null
...

so könntest du folgefälle leicht erkennen. einzelfälle wären fälle, deren id in keinem anderen fall als folge-id aufgeführt sind. die 3 wäre hier so ein fall, die 5 nicht, da ihre id bei der 4 als folge eingetragen ist. einzge frage die mir bleibt: lässt sich das gescheit auslesen? das klingt nach rekursion und da steh ich grad aufm schlauch ob und wie das geht ^^
 
Da hätte ich dann aber das gleiche Problem. Woher weiß ich jetzt, welcher Fall von welchem der Folgefall ist?

Klar, in meiner Testtabelle kann ich das von Hand eintragen. Da sehe ich ja, welcher Fall nach welchem kommt. Aber ich müsste das auch automatisiert erkennen können, weil in meiner großen Tabelle mehr Datensätze drin sind. Da kann ich das nicht so einfach von Hand eintragen.

Es ist einfacher zu warten, das stimmt. Aber ich habe das gleiche Problem, wenn ich nun die Folge-ID in meine Tabelle eintragen will.

@DarkMo: Ja, wie in deiner Tabelle soll es aussehen. Ich kann es auch alles aus einer Tabelle ziehen. Nur wie gesagt, ich habe noch keine Folge-ID eingetragen und die muss ja auch durch eine Query ermittelt werden.
 
Du könntest die Folge-ID einmalig automatisiert eintragen - für diese automatische Änderung sind die Ärzte ja irrelevant und ohne Arzt-ID geht es ja.
 
hmm, also das sollte die quell-tabelle sein, nicht die ergebnistabelle. aber beim durchdenken fiel mir noch auf, das "Folge" blöde ist ^^ eher müsste mans andersherum aufziehen, also das ding vllt "Nach" nennen oder so. oder Folgt_auf, wad weis ich ^^
Tabelle: Fälle
ID|Patient|Arzt|Aufnahme|Entlassung|Folgt_auf
...
3|12345|1|01.01.2014|01.03.2014|null
4|12345|2|01.03.2014|01.06.2014|3
5|12345|3|01.07.2014|01.09.2014|4
...

weil beim erstellen der datensätze, sind die folgefälle ja noch garnich bekannt. die vorgänger aber schon. man tippelt also ein, patient 12345 wird vom... bis... bei arzt bla neu (folgt_auf = null) aufgenommen. danach das selbe in grün, nur eben mit dem vermerk, dass dies ein folgefall zu dem von eben ist. damit das funzt, muss man halt jeweils die id des erstellten falles mit ausgeben lassen, aber das sollte ja das geringste sein.

nur wie gesagt, wie man dann alle zusammenhängenden fälle ermittelt, das wüsst ich jetz auf anhieb nicht. fall und ggf folgefall würd ich noch hinbekommen, aber das ganze "variabel" (also wohl eben rekursiv) umzusetzen, dazu fehlt mir grad die idee ^^ aber wenn ben meint, das es prinzipiel geht (dächte auch schonmal, davon gelesen zu haben), dann sollte das ja auch das geringere prob sein *denk*
 
@BenRo: Ich versuche es mal

@DarkMo: Leider sind die Datensätze ja bereits in der Tabelle und ich weiß eben nicht, was wovon der Folgefall ist. Wenn man jetzt so nachschauen würde, dann würde man es wahrscheinlich sehen, aber es sind halt sehr viele Daten und das dauert von Hand zu lange. Das Feld "Folge-ID" war einfach noch nicht vorhanden, als die Daten erstellt wurden. Oder anders gesagt: Stell Dir vor, irgendein Depp hat die Daten eingetragen aber immer vergessen, die Folge-ID bzw. "Folgt_auf" einzutragen :D
 
Ich hatte es jetzt mit der Folge-Fall-ID gelöst, hat auch geklappt. Dann habe ich aber bemekrt, dass die ID in der Datenbank nicht aufsteigend vergeben wurde. Heißt, dass der ein Fall die ID 100 hat, während der Folgefall die ID 50 hat. Somit ist meine Bedingung zwar für meine Testtabelle gut, aber nicht in meiner echten Datenbank:

[...] and b.fallid > a.fallid

Ich muss es irgendwie anders lösen... Ohne Folge-ID. Einfach eine Unterabfrage, in der ich das nächste kleinste Datum für die Personen-ID abfrage. Ich weiß nur nicht, wie ...

EDIT: Ich konnte es nun lösen. Wen es interessiert:

select a.id, a.aufn, a.entl, a.arzt, b.aufn folge_aufn, b.entl folge_entl, b.arzt folge_ik, a.fallid, b.fallid folge_id
from s_114941_test a, s_114941_test b
where a.id = b.id
and a.fallid <> b.fallid
and b.aufn = (SELECT min(c.aufn)
from s_114941_test c
where c.id = a.id
and c.fallid <> a.fallid -- Damit bei 1-Tages-Aufenthalten nicht ein Fall als Folgefall für sich selbst interpretiert wird
and c.aufn >= a.entl)

union all

select distinct a.id, a.aufn, a.entl, a.arzt, b.aufn folge_aufn, b.entl folge_entl, b.arzt folge_ik, a.fallid, b.fallid folge_id
from s_114941_test a, s_114941_test b
where a.id = b.id
and a.fallid <> b.fallid
and b.aufn = (SELECT min(c.aufn)
from s_114941_test c
where not exists (select 1 from s_114941_test c where c.id = a.id
and c.fallid <> a.fallid -- Damit bei 1-Tages-Aufenthalten nicht ein Fall als Folgefall für sich selbst interpretiert wird
and c.aufn >= a.entl);

Im oberen Teil sind alle Fälle, die einen Folgefall haben. Unter dem UNION ALL sind die Fälle, die keinen Folgefall haben.

Danke für eure Hilfe :)
 
Zuletzt bearbeitet:
Zurück