Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   SELF JOIN - Beispiel konstruieren (https://www.delphipraxis.net/138734-self-join-beispiel-konstruieren.html)

Jürgen Thomas 16. Aug 2009 17:11

Datenbank: beliebig • Zugriff über: beliebig

SELF JOIN - Beispiel konstruieren
 
Hallo,

ich befasse mich zz. etwas grundsätzlicher mit SQL und mögliche jetzt zum SELF JOIN sinnvolle Beispiele basteln. So könnten doppelte Datensätze gefunden werden; bei Andreas Kosch finde ich wiederholt die Berechnung der Differenz von km-Ständen.

Bei einer "eigenen Situation" komme ich nicht auf die zündende Idee. Ich habe eine Tabelle Schadensfaelle, bei der eine Versicherung für jedes Fahrzeug die Vorfälle (zusammen mit Schadenshöhe usw.) registriert. Diese Tabelle enthält auch ein Feld Datum. Ich möchte jetzt die Abstände zwischen den Vorfällen für ein bestimmtes Fahrzeug bestimmen. (Die ganzen WHERE-Bedingungen kann ich mir selbst zusammenreimen.)

Das folgende genügt natürlich noch nicht:
SQL-Code:
select a.Datum, b. Datum, a.Datum - b.Datum
from Schadensfaelle a
join Schadensfaelle b on b.id > 0  // nur fiktiv, damit eine Bedingung notiert ist
where a.Datum > b.Datum
Dies liefert zu viele Informationen:
Code:
DATUM          DATUM1       SUBTRACT
03.06.2008      01.02.2008        123
13.09.2008      01.02.2008        225  //  diese Zeile stört
13.09.2008      03.06.2008        102
Gibt es einen einfachen Trick, sodass sowohl bei a.Datum als auch bei b.Datum jedes Datum nur einmal auftaucht und die zeitliche Reihenfolge eingehalten wird?

Recht herzlichen Dank! Jürgen

mkinzler 16. Aug 2009 17:37

Re: SELF JOIN - Beispiel konstruieren
 
Distinct oder wenn du festlegen willst welches Datum genommen wird ein MIN/MAX und Gruppierung

Jürgen Thomas 16. Aug 2009 17:44

Re: SELF JOIN - Beispiel konstruieren
 
DISTINCT klingt gut, danke! Jürgen

DeddyH 16. Aug 2009 19:10

Re: SELF JOIN - Beispiel konstruieren
 
MIN erscheint mir aber geeigneter. Du willst ja den kürzesten zeitlichen Abstand, oder nicht?

Jürgen Thomas 17. Aug 2009 08:05

Re: SELF JOIN - Beispiel konstruieren
 
So, ich habe jetzt alles ausprobiert und eure Tipps berücksichtigt und habe das gewünschte Ergebnis erhalten:
SQL-Code:
select a.Datum, b.Datum, a.Datum - b.Datum
from Schadensfaelle a
join Schadensfaelle b
  on b.Datum = ( select max(c.Datum) from Schadensfaelle c where a.Datum > c.Datum )
MAX deshalb, weil aus c das größte Datum gesucht wird, das kleiner als a.Datum ist.
Code:
DATUM          DATUM1       SUBTRACT
03.06.2008      01.02.2008        123
13.09.2008      03.06.2008        102
Es gefällt mir noch nicht, dass ich die Tabelle wegen der MAX-Bestimmung noch ein drittes Mal einbinden muss. Die Geschwindigkeit beeinträchtigt das wohl nicht, da dürfte jedes DBMS "intelligent" genug sein; aber die Übersichtlichkeit leidet doch etwas.

Gibt es noch bessere Vorschläge?

Danke jedenfalls

DeddyH 17. Aug 2009 08:40

Re: SELF JOIN - Beispiel konstruieren
 
Ausgehend von der Annahme, dass in der Tabelle auch die Fahrzeug-Id hinterlegt ist, könnte man das so machen:
SQL-Code:
select a.Fahrzeug_Id, a.Datum, b.Datum, MIN(a.Datum - b.Datum)
from Schadensfaelle a
join Schadensfaelle b
  on b.Fahrzeug_Id = a.Fahrzeug_Id
group by a.Fahrzeug_Id, a.Datum, b.Datum

Jürgen Thomas 17. Aug 2009 09:33

Re: SELF JOIN - Beispiel konstruieren
 
Hallo Detlef,

klappt leider genausowenig wie meine früheren Versuche. Zum einen muss noch "where a.Datum > b.Datum" hinzugefügt werden; es kommt aber immer die Ausgabe mit 3 Zeilen (wie oben), weil die MAX-Bedingung fehlt.

Die Fahrzeug_ID steht in einer anderen Tabelle, die alle Fahrzeuge zu einem Schadensfall verknüpft; aber das können wir im Moment vernachlässigen und so tun, als stünde sie direkt zur Verfügung.

Weitere Ideen? Jürgen

DeddyH 17. Aug 2009 09:59

Re: SELF JOIN - Beispiel konstruieren
 
Nun hab ich sowas ähnliches wie Du (wobei man vermutlich die Join-Bedingung weglassen kann, ich hab es nicht getestet):
SQL-Code:
SELECT A.Datum, B.Datum, MIN(A.Datum - B.Datum)
FROM Schadensfaelle A
JOIN Schadensfaelle B
  ON A.Datum > B.Datum
GROUP BY A.Datum, B.Datum
HAVING B.Datum = (
   SELECT MAX(Datum) FROM Schadensfaelle
   WHERE Datum < A.Datum)
[edit] Das MIN kann so vermutlich auch entfallen, einfach mal ausprobieren. [/edit]

Jürgen Thomas 17. Aug 2009 10:33

Re: SELF JOIN - Beispiel konstruieren
 
Hallo Detlef,

diese Lösung ist faktisch identisch mit meiner in #5. Das MIN kann in der Tat entfallen. Ich hatte die MAX-Abfrage in die ON-Bedingung eingebaut, während du sie in die HAVING-Klausel verschoben hast. Da dürfte mein Verfahren noch etwas effektiver sein (auch wenn es nicht so schön aussieht und der Feststellung in meiner anderen Diskussion widerspricht, was zur ON-Bedingung und was zur WHERE-Bedingung gehören soll).

Auf das JOIN kann sicher nicht verzichtet werden (ich wüsste auch nicht wie), weil ich ein und dasselbe Feld zweimal aus verschiedenen Datensätzen benötige.

Wenn es keine wesentlichen neuen oder besseren Vorschläge gibt, können wir es wohl dabei belassen.

Danke! Jürgen

DeddyH 17. Aug 2009 10:36

Re: SELF JOIN - Beispiel konstruieren
 
Ich meinte nicht den Join an sich, sondern dessen Bedingung, da diese ja quasi durch die HAVING-Klausel sowieso hineinkommt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:19 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz