Einzelnen Beitrag anzeigen

alex517

Registriert seit: 23. Nov 2004
Ort: Bernau b. Berlin
273 Beiträge
 
Delphi XE5 Enterprise
 
#7

Re: JOINs und zusätzliche Bedingungen

  Alt 10. Aug 2009, 20:28
Hi,

ich denke es ist durchaus manchmal notwendig im "ON" außer der Join- auch
andere Bedingungen anzugeben.

folgendes Bsp.
Gesucht sind ALLE Personen mit der Anzahl der zugeordneten Verträge:
SQL-Code:
select
  P.ID,
  P.PERSONEN_NAME,
  count(A.ID)
from
  PERSON P
  left join EAUFTRAG A on (A.PATIENT_ID = P.ID)
group by
  P.ID,
  P.PERSONEN_NAME
Im Ergebnis erhält man alle Personen in der Anzahl zugeordnete Verträge,
inclusive der Personen mit 0 Aufträgen.

Wenn man jetzt wieder ALLE Personen und die Anzahl Verträge alledings
begrenzt auf das einen Zeitraum (z.B. 2007) sehen will, könnte man
als Erstes auf die Idee kommen einfach in der Where-Klausel den
Zeitraum der Auftrage einzugrenzen:
SQL-Code:
select
  P.ID,
  P.PERSONEN_NAME,
  count(A.ID)
from
  PERSON P
  left join EAUFTRAG A on (A.PATIENT_ID = P.ID)
where
  (A.DATUM_VON between '01.01.2007and '31.12.2007')
group by
  P.ID,
  P.PERSONEN_NAME
Damit bekommt man jetzt zwar alle Personen die mindestens eine Vertrag
in 2007 haben, aber alle anderen Personen ohne Vertrage (count(A.ID) = 0) fehlen!

Warum? Weil in der "verjointen" Ergebnismenge, über diese wird das count() ausgeführt,
nur Daten enthalten sind für die (A.DATUM_VON between '01.01.2007' and '31.12.2007') zutrifft.
Mit dieser Bedingung wird das "left join" sozusagen ausgehebelt.

Gut, also müssen in der "verjointen" Ergebnismenge auch Datensätzen mit A.DATUM_VON is NULL,
also Personen ohne Vertrag, enthalten sein.
Die Where-Klausel wird erweitert:
SQL-Code:
select
  P.ID,
  P.PERSONEN_NAME,
  count(A.ID)
from
  PERSON P
  left join EAUFTRAG A on (A.PATIENT_ID = P.ID)
where
  A.DATUM_VON is null or (A.DATUM_VON between '01.01.2007and '31.12.2007')
group by
  P.ID,
  P.PERSONEN_NAME
Damit erhält man genau das gewünschte Ergebnis:
Alle Personen mit der Anzahl Verträge im Jahr 2007 incl. Personen ohne Verträge.

Wenn man sich jetzt (z.B. im IBExpert) die Anzahl der Read-Zugriffe ansieht,
erhält man im Beispiel
Person, nicht indiziert Reads: 167
EAuftrag, indiziert Reads: 644

Stellt man jetzt aber die SQL um, in dem man bereits im "..ON.." den Zeitraum einschränkt:
SQL-Code:
select
  P.ID,
  P.PERSONEN_NAME,
  count(A.ID)
from
  PERSON P
  left join EAUFTRAG A on (A.PATIENT_ID = P.ID and A.DATUM_VON between '01.01.2007and '31.12.2007')
group by
  P.ID,
  P.PERSONEN_NAME
so erhält man die gleiche Ergebnismenge aber mit folgende Read-Zugriffe:
Person, nicht indiziert Reads: 167
EAuftrag, indiziert Reads: 65

Warum?
Weil die Anzahl der Daten aus EAUFTRAG bereits VOR dem JOIN eingeschränkt wurde!
Es müssen also erheblich weniger Daten gezählt werden.


alex
Angehängte Dateien
Dateityp: zip testdb2_fbk_657.zip (15,7 KB, 1x aufgerufen)
Dateityp: zip testdb2_sql_135.zip (14,8 KB, 1x aufgerufen)
Alexander
  Mit Zitat antworten Zitat