Komplexes JOIN-Statement über 5 Tables (hierarchie)

MMachete

Neuer Benutzer
Beiträge
3
Hallo liebe Datenbank-Spezialisten!
Habe folgendes Problem bei einem Query in meiner Datenbank.
Wie man im Bild erkennen kann, handelt es sich um eine Art "Quizz"-Applikation/Spiel.
Es gibt 1-n Kategorien (zB 1), dazu 1-n Subkategorien (zB 1.1) und dafür wieder beliebig viele Sub-Subkategorien (zB 1.1.1) in welchen sich dann die Fragen befinden. Fragen können mit Werten von 1-5 bewertet werden.

Mein Ziel ist es einen Query zu schreiben, der alle Ebenen1-Objekte anzeigt und ihren kumulierten Wert (SUM()) aller Fragen, die sich in dieser Kategorie (Ebene) befinden.
Versucht habe ich das zuerst mit einem FULL JOIN. Result set zeigt: Nur die erste Kategorie und die Summe ALLER Fragen!

Dann mit Subselect, Resultat: Es werden alle Ebene1-Objekte angezeigt und in der zweiten Column wieder der Gesamtwert ALLER Fragen.

Wie kann ich in dem Query explizit zwischen Ebenen differenzieren?

Bitte um Hilfe!! Queries kann ich gerne posten, sind halt ziemlich lange...


MFG MM
 

Anhänge

  • ausschnitt mydb.jpg
    ausschnitt mydb.jpg
    41,4 KB · Aufrufe: 11
Werbung:
Hallo liebe Datenbank-Spezialisten!
Habe folgendes Problem bei einem Query in meiner Datenbank.
Wie man im Bild erkennen kann, handelt es sich um eine Art "Quizz"-Applikation/Spiel.
Es gibt 1-n Kategorien (zB 1), dazu 1-n Subkategorien (zB 1.1) und dafür wieder beliebig viele Sub-Subkategorien (zB 1.1.1) in welchen sich dann die Fragen befinden. Fragen können mit Werten von 1-5 bewertet werden.

Mein Ziel ist es einen Query zu schreiben, der alle Ebenen1-Objekte anzeigt und ihren kumulierten Wert (SUM()) aller Fragen, die sich in dieser Kategorie (Ebene) befinden.

Bilder sind Mist. Egal. Du scheinst sowas zu haben:

Code:
test=*# select * from c;
 id
----
  1
  2
(2 rows)

test=*# select * from c1;
 id | c
----+---
  1 | 1
  2 | 1
(2 rows)

test=*# select * from c2;
 id | c1
----+----
  1 |  1
  2 |  1
(2 rows)

test=*# select * from c3;
 id | c2
----+----
  1 |  1
  2 |  1
(2 rows)

test=*# select * from c4;
 id | c3 | wert
----+----+------
  1 |  1 |  10
  2 |  1 |  20
(2 rows)

und suchst:

Code:
test=*# select c.id, sum(c4.wert) from c left join c1 on c.id=c1.c left join c2 on c1.id=c2.c1 left join c3 on c2.id=c3.c2 left join c4 on c3.id=c4.c3 group by c.id;
;
 id | sum
----+-----
  1 |  30
  2 |
(2 rows)

Andreas
 
Hallo Andreas, danke für deine Antwort.
Den von dir beschriebenen Query habe ich bereits so formuliert (nur ohne GROUP BY). Mit GROUP BY funktioniert es genausowenig!
Bei mir sieht er folgendermaßen aus:
Code:
Select
  ebene1.e1bez,
  Sum(bewertung.wert) as punkte,
From
  bewertung  Join
  erhebung On bewertung.eid = erhebung.eid  Join  
  frage On bewertung.frid = frage.frid  Join
  ebene3 On frage.e3id = ebene3.e3id  Join
  ebene2 On ebene3.e2id = ebene2.e2id  Join
  ebene1 On ebene2.e1id = ebene1.e1id

Result-Set:
Code:
e1bez | punkte
------+--------
1        | 7
2        | 7

Obwohl unterschiedliche Bewertungen (Werte) in den jeweiligen Fragen hinterlegt wurden, sind die Wertesummen in beiden Ebene1-Objekten gleich.
Es wird alles summiert und auf die Hierarchie-Relation keine Rücksicht genommen.

Mein Subquery:

Code:
Select
                  ebene1.e1id,
                    ( Select sum(b.wert)
                      from bewertung b
                          left join frage f on b.frid=f.frid
                          left join ebene3 e3 on f.e3id=e3.e3id
                          left join ebene2 e2 on e3.e2id=e2.e2id
                          left join ebene1 e1 on e2.e1id=e1.e1id
                      ) as punkte,
                  ebene1.e1bez,
                  ebene1.pkte
              From
                  ebene1
              where ebene1.e1bez=1 or 2
              group by ebene1.e1id';

Result-Set:
Code:
e1bez | punkte
------+--------
1        | 14
2        | 14

Hier dasselbe Problem. Die beiden obersten Ebenen haben die gleichen Werte. Nur ist der Wert bei diesem Query doppelt so hoch.
Wie muss ich den Query umformulieren, sodass zwischen Ebenen unterschieden wird und die Werte korrekt aufsummiert werden?

MFG Max
 
Hallo Andreas, danke für deine Antwort.
Den von dir beschriebenen Query habe ich bereits so formuliert (nur ohne GROUP BY). Mit GROUP BY funktioniert es genausowenig!
Bei mir sieht er folgendermaßen aus:

MFG Max

Was Du zeigst ist schon mal ein Syntaxfehler. Zumindest in allen 'richtigen' Datenbanken. Also alles != MySQL : in Abfragen mit einer Aggregation müssen alle Spalten des Resultates entweder in einer Aggregation oder im GROUP BY sein. MySQL schert sich hier (und anderswo) einen Scheiß um Normen und Syntax und korrekte Ergebnisse, und ich hab keinen weiteren Bock drauf, da noch viel Forschungsarbeit zu investieren, wie man an all den Fehlern von MySQL ohne blaue Augen vorbeimanövriert. Deal with it, or change it. In der Welt der freien Datenbanken ist alles besser als MySQL, angefangen von SQLlite bis PostgreSQL. Bei kommerziellen sowieso. Es gibt (für mich) keinen einzigen Grund, diesen Müll zu verwenden.
 
Sehr dankbar wäre ich für konstruktive und kompetente Beiträge, die sachlich auf die Problemstellung eingehen. MfG

Sorry, aber ich hab Dir eine Lösung gezeigt. Ich denke, diese funktioniert. Wenn das unter MySQL nicht geht, dann ist MySQL das falsche Werkzeug, in meiner Lösung ist exakt nix, was irgendwie rein nur unter PG funktioniert. Auch kenne ich Deine Ausgangsdaten nicht.
Dein "funktioniert es genausowenig!" ist keine nachvollziehbare Beschreibung Deines Problems.
Davon abgesehen, nochmals: ich denke, daß die von mir gezeigte Lösung korrekt ist und unter allen möglichen DB-Systemen funktioniert.

Die Tatsache, daß, Zitat: "Den von dir beschriebenen Query habe ich bereits so formuliert (nur ohne GROUP BY)" unter MySQL ohne Syntaxfehler läuft ist kein tolles Feature von MySQL, sondern einfach nur FAIL. Dafür kannst Du nichts, ich weiß. Aber gestehe mir zu, daß ich einfach zum Ausdruck bringe, daß Du offenbar das falsche Werkzeug nutzt.
 
Code:
Select
  ebene1.e1bez,
  Sum(bewertung.wert) as punkte,
From
  bewertung  Join
  erhebung On bewertung.eid = erhebung.eid  Join
  frage On bewertung.frid = frage.frid  Join
  ebene3 On frage.e3id = ebene3.e3id  Join
  ebene2 On ebene3.e2id = ebene2.e2id  Join
  ebene1 On ebene2.e1id = ebene1.e1id

Also alles != MySQL : in Abfragen mit einer Aggregation müssen alle Spalten des Resultates entweder in einer Aggregation oder im GROUP BY sein.

Ich muss da Andreas vollkommen Recht geben. Davon abgesehen das ebene1.e1bez auch unter MySQL ein Zufallswert. Bei einem Wechsel des Betriebssystems oder der MySQL Version kann sich das Ergebnis ändern.

Wenn du auf kaputten Code bestehst kann dir Keiner zuverlässig helfen.
 
Werbung:
Sehr dankbar wäre ich für konstruktive und kompetente Beiträge, die sachlich auf die Problemstellung eingehen. MfG

Damit wir hier noch zu einem Ergebniss kommen:

  • erstelle vereinfachte Tabellen
  • fülle diese mit simplen Daten
  • fange mit 2 Tabellen an und baue Deine Abfrage auf
  • kontrolliere, ob das Ergebniss stimmt
  • gehe 2 Schritte zurück und nehme 1 Tabelle mehr in den JOIN
  • alle Tabellen im JOIN drin? Stimmt das Resultat?


Behalte im Auge, daß MySQL sich nicht nach der SQL-Spezifikation richtet. Beachte die Regel, daß in Abfragen mit Aggregationen alle Spalten des Ergebnisses entweder aggregiert oder gruppiert sein müssen, auch wenn MySQL zu doof ist, das zu prüfen bzw. durchzusetzen. Schalte den Strict-Mode an ( http://dev.mysql.com/doc/refman/5.1/de/server-sql-mode.html ) oder, besser: nutze eine Datenbank, die sich normgerecht verhält und daher besser zum Lernen geeignet ist. Das kann z.B. SQLlite oder PostgreSQL sein.
 
Zurück
Oben