Kerstin: Joins verknüpfen

Beitrag lesen

Hallo Sven,

Super vielen Dank für Deine ausführliche Antwort. Ich benutze Oracle. Aber ich denke mit Deiner Lösung werd ich es dann da auch hinbekommen.

CREATE TABLE g10_ebene_temp AS
SELECT distinct ebene, thema FROM g10_ebene, g10_themen
  WHERE onr=#FORM.gebaeude#

CREATE TABLE g10_ebene_thema_temp AS
SELECT distinct ebene, id FROM g10_themen, g10_ebene_thema
  WHERE onr=#FORM.gebaeude#
  AND thema=id

Um Gottes Willen! Das ist ja der Performance-Killer hoch 10!

Das hab ich auch befürchtet, deshalb hab ich ja mal hier nachgefragt ;-)

Mit dem Equi-Join erzeugst du erstmal eine Riesentabelle. Jeder Eintrag aus Tabelle 1 wird mit jedem Eintrag aus Tabelle 2 verknüpft, so daß am Ende (Zeilen Tabelle 1) x (Zeilen Tabelle 2) Zeilen entstehen. Von allen JOINs ist dies der denkbar schlechteste, wenn du nicht wirklich alle Zeilen kreuzweise mit allen anderen Zeilen verknüpft haben möchtest. Es gibt in der Regel bessere Methoden.

Ich nehm ja nicht die ganze Tabelle, sondern nur die Ebenen von dem gewählten Gebäude (von über 30 Gebäuden). Bei 8 Ebenen und 16 Themen sind es dann 128 Zeilen und so viele Zeilen soll das Ergebnis am Ende ja auch haben (alle Themen für jede Ebene).

Mit SELECT DISTINCT sortierst du dann alle Zeilen aus, die doppelte Einträge in den Spalten "ebene" und "thema" haben. SELECT DISTINCT isb ebenfalls langsam, da sehr viele Vergleiche ausgeführt werden müssen, um doppelte Einträge zu eliminieren.

Es gibt bessere Methoden, dein Ziel zu erreichen. Beispielsweise gibts den LEFT OUTER JOIN. Aber mal der Reihe nach:

Du hast 3 Tabellen für Ebenen, Themen und zugeordnet Ebene<->Thema

Du willst für eine einzelne Ebene wissen:
Welche Themen sind der Ebene zugeordnet, und welche Themen gibts insgesamt, so daß man ein Checkboxformular damit befüllen kann.

Als Ergebnis stellst du dir also folgende Tabelle vor:

Ebene Thema Themaname
  1     1    Thema1
  1     2    Thema2
  -     3    Thema3
  1     4    Thema4

Drei Themen sind Ebene 1 zugeordnet (ich abstrahiere mal), und es gibt insgesamt 4 Themen.

Die Daten kommen aus folgenden Einzeltabellen:
Tabelle Ebene:
EbeneID  weitere Infos
#1       Info zu Ebene 1

Tabelle Thema
ThemaID  Themaname
#1       Thema1
#2       Thema2
#3       Thema3
#4       Thema4

Tabelle Thema<->Ebene
ID EbeneID ThemaID
#1   #1     #1
#2   #1     #2
#3   #1     #4

Was willst du genau wissen? Primär: Welche Themen gibts alle? Das wird also dein SELECT.

Dann: Welches der vorhandenen Themen ist mit Ebene 1 verknüpft? Denn diese Themen sollen ja selektiert erscheinen. Das wird dein erster JOIN (welcher, ist noch zu entscheiden...).

Und als drittes: Brauchst du noch weitere Informationen zu Ebene 1, die in der Ebenen-Tabelle stehen? Das wäre dann der zweite JOIN.

Wichtig ist, daß die IDs die Verknüpfung korrekt herstellen. Als "primary auto_increment key" ist sowas immer gut und stellt die Datenintegrität sicher.

Zurück zum JOINen:

SELECT thema.themenID, thema.spalte1, thema.spalte2 FROM thema
Das sorgt dafür, daß einfach alle vorhandenen Themen selektiert werden. Easy. :)

Jetzt muß dann, wenn Ebene 1 mit dem Thema verknüpft ist, das in der Tabelle deutlich gemacht werden. Wenn Ebene 1 nicht verknüpft ist, soll die Themenzeile aber erhalten bleiben. Für sowas ist der LEFT OUTER JOIN gut, denn der macht genau das. Siehe auch http://www.little-idiot.de/mysql/mysql-118.html

SELECT t.themaID, t.Themaname, te.ebeneID, te.themaID
FROM thema AS t
LEFT OUTER JOIN themaebene AS te
ON t.themaID=te.themaID AND te.ebeneID = 1

Im Select werden alle Spalten der entstehenden Tabelle gelistet. Ich hab' der Einfachheit halber mit Alias-Namen für die Tabellen gearbeitet.

Wenn du das Ergebnis siehst, sollte das schon deinen Wünschen entgegenkommen: Alle Themen vorhanden, und die Themen der Ebene 1 haben eine Kennzeichnung.

Das ist im Prinzip schon, was du willst. Wenn noch die Daten der Ebene 1 angehängt werden, machst du einen normalen JOIN auf diese Tabelle:

SELECT t.themaID, t.Themaname, te.ebeneID, te.themaID, e.ebeneID, e.spalte1, e.spalte2
FROM thema AS t
LEFT OUTER JOIN themaebene AS te
ON t.themaID=te.themaID AND te.ebeneID = 1
JOIN ebene AS e
ON te.ebeneID = e.ebeneID
ORDER BY irgendwas
LIMIT BY irgendwas

Fertig. :) Jedenfalls theoretisch. Ich hab's in einem anderen Zusammenhang, aber mit ziemlich exakt deiner Aufgabenstellung schon mal so hingekriegt - wenn Fehler in dieser Lösung drin sind, dann liegts an Flüchtigkeitsfehlern und Kleinigkeiten, die aus Versehen reingerutscht sind, aber nicht an der grundsätzlichen Unmöglichkeit.

Folge dem Link und probiere selbst einmal ein wenig rum. Mit SQL ist sehr viel mehr möglich, als der Standardbenutzer weiß. :)

Jetzt weiss ich doch, dass es funktioniert. Da war ich mir nämlich nicht sicher. Hatte schon eine Weile rumprobiert, aber ohne Erfolg und da hab ichs dann erstmal so gemacht, wie es sicher ging ;-)
Danke, werd dann mal ein bisschen rumprobieren :-)

Kerstin