Matze: MySQL - komplexer SELECT COUNT mit Subquery

Hallo NG,

ich habe einen relativ komplexen SQL-Select. Kurz zur Struktur:

Ich habe eine Tabelle (form1) mit einer Subtabelle (f1_sub_from). In der Tabelle form1 ist jeweils die ID der Sätze aus f1_sub_form enthalten, bzw. auch direkt auswertbare Daten.

Ich habe nachstehenden SQL-Befehl verbrochen :-):
SELECT count(*) as ANZAHL FROM form1 INNER JOIN f1_sub_form ON (form1.F1_WERT033 = f1_sub_form.F1SUB_ID
and f1sub_wert NOT IN ('3', '8', '9', '10', '12', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56'))
WHERE (form1.F1_WERT056 = truncate('1',0) AND (truncate('6',0) < (SELECT COUNT(*) As ANZAHL2 from form1, f1_sub_form WHERE F1_WERT119 = f1sub_id AND f1sub_wert <> truncate('60',0))))
AND form1.F1_KEY1 = '6054061' AND F1_MODUL = '16/1'

Der INNER Join gibt die Anzahl der Sätze zurück, die für F1_WERT033 zutreffen können. Da maximal 9 Sätze für F1_WERT033 vorhanden sein können, teste ich dann ob ANZAHL = 9 ist. Der Part F1_WERT056 = truncate('1',0) ist unkritisch.
Das Problem ist der letzte Teil. In F1_WERT119 können maximal 6 Subsätze eingetragen werden. Ich muss nun zusätzlich prüfen ob ein Wert '60' eingetragen ist.
Nur finde ich keine Möglichkeit das SQL nur ansatzsweise darauf reagiert.
Hat jemand eine Idee oder einen besseren Lösungsansatz. Ich kann leider nicht mit Union arbeiten, da ich als Ergebnis einen Satz mit einer Zahl weiter arbeiten muss.

Danke im voraus.
Grüsse Matze

  1. yo,

    zum einen sind die tabellen und spalten-namen meiner meinung nach ein wenig unglücklich gewählt. es is nur ein vorschlag, aber ich würde versuchen namen zu nehmen, aus denen man den sinn lesen kann. das macht vor allem für aussenstehende einfacher zu verstehen.

    Ich habe eine Tabelle (form1) mit einer Subtabelle (f1_sub_from). In der Tabelle form1 ist jeweils die ID der Sätze aus f1_sub_form enthalten

    ok, eine 1:n beziehung der beiden tabellen, wobei es subtabellen meiner meinung nach nicht gibt. aber ist auch nicht so wichtig. ich habe mal versucht, deine alte abfrager ein wenig zu sortieren.

    SELECT count(*) as ANZAHL
    FROM form1, f1_sub_form
    WHERE form1.F1_WERT033 = f1_sub_form.F1SUB_ID
    AND f1sub_wert NOT IN ('3', '8', '9', '10', '12')
    AND f1sub_wert NOT BETWEEN 16 AND 56
    AND form1.F1_WERT056 = truncate('1',0)
    AND form1.F1_KEY1 = '6054061'
    AND F1_MODUL = '16/1'
    AND truncate('6',0) <
       (SELECT COUNT(*) As ANZAHL2
        FROM form1, f1_sub_form
        WHERE F1_WERT119 = f1sub_id
        AND f1sub_wert <> truncate('60',0)
       )

    der erste kritische punkt ist, du hast keine aliasnamen für die tabellen verwendet. das mag bei einem subselect vielleicht unkritisch sein, aber trotzdem stehen in einer abfrage, zweimal die gleichen tabellen und ich würde dann lieber alias namen einsetzten, um die spalten eindeutig unterscheiden zu können.

    der zweite kritische punkt ist meiner meinung nach der, dass die beiden tabellen mit der 1:n beziehung scheinbar über verschiedene spalten miteinander verbunden sind oder aber in dem subselect fehlt die JOIN bedingung.

    ich vermute, dein problem könnte in dem daten-desgn liegen. aber dafür wäre es hilfreich, wenn du noch mal genauer erklären könntest, was genau du machen willst und wie deine tabellen genau aussehen, spriche welche spalten wofür stehen.

    Ilja

    1. Hallo Yo,

      erstmal danke für Deine Antwort.
      Nunja, was die Namensgebung angeht. Das Datenmodell ist absolut abstrakt. Womit die Namen etwas ungewohnt sind. right :-(.

      Deine Sortierung ist soweit völlig korrekt. Das Problem an dem Befehl ist der Part nach F1_MODUL = '16/1'.
      Natürlich ist es keine Subtabelle sondern wie Du schon gesagt hast hat die FORM1 zweimal eine 1:N-Beziehung zur F1_SUB_FROM.
      Einmal im Feld F1_WERT033 und einmal im Feld F1_WERT119. In der F1_SUB_FORM sind für F1_WERT033 9 Datensätze vorhanden, für F1_WERT119 sind es 6 Datensätze.
      Geprüft werden muss, ob aus der Werteliste für F1_WERT033 ein Wert eingetragen werden muss, was auch problemlos funktioniert. Wenn als ANZAHL der Wert 9 selektiert wird, ist kein Wert eingetragen und kann entsprechend ausgewertet werden.
      Nun muss ich zusätzlich prüfen, ob für F1_WERT119 der WERT '60' in die F1_SUB_FORM eingetragen ist.
      Meine Idee war eben das als Subselect abzufragen. Jedoch bekomme ich als Ergebnis immer ANZAHL = 9. Den Teil Subselect ignoriert er völlig.
      Ich muss das ganze in einem einzigen SQL-Befehl unterbringen und mir fehlt z.Z. offen gestanden eine Idee wie man das ganze noch anders Abfragen könnte. Zumal zumindest mit meiner Version MySQL noch keine Views unterstützt.

      Ich hoffe das war jetzt etwas verständlicher.
      Viele Grüsse
      Matze

      yo,

      zum einen sind die tabellen und spalten-namen meiner meinung nach ein wenig unglücklich gewählt. es is nur ein vorschlag, aber ich würde versuchen namen zu nehmen, aus denen man den sinn lesen kann. das macht vor allem für aussenstehende einfacher zu verstehen.

      Ich habe eine Tabelle (form1) mit einer Subtabelle (f1_sub_from). In der Tabelle form1 ist jeweils die ID der Sätze aus f1_sub_form enthalten

      ok, eine 1:n beziehung der beiden tabellen, wobei es subtabellen meiner meinung nach nicht gibt. aber ist auch nicht so wichtig. ich habe mal versucht, deine alte abfrager ein wenig zu sortieren.

      SELECT count(*) as ANZAHL
      FROM form1, f1_sub_form
      WHERE form1.F1_WERT033 = f1_sub_form.F1SUB_ID
      AND f1sub_wert NOT IN ('3', '8', '9', '10', '12')
      AND f1sub_wert NOT BETWEEN 16 AND 56
      AND form1.F1_WERT056 = truncate('1',0)
      AND form1.F1_KEY1 = '6054061'
      AND F1_MODUL = '16/1'
      AND truncate('6',0) <
         (SELECT COUNT(*) As ANZAHL2
          FROM form1, f1_sub_form
          WHERE F1_WERT119 = f1sub_id
          AND f1sub_wert <> truncate('60',0)
         )

      der erste kritische punkt ist, du hast keine aliasnamen für die tabellen verwendet. das mag bei einem subselect vielleicht unkritisch sein, aber trotzdem stehen in einer abfrage, zweimal die gleichen tabellen und ich würde dann lieber alias namen einsetzten, um die spalten eindeutig unterscheiden zu können.

      der zweite kritische punkt ist meiner meinung nach der, dass die beiden tabellen mit der 1:n beziehung scheinbar über verschiedene spalten miteinander verbunden sind oder aber in dem subselect fehlt die JOIN bedingung.

      ich vermute, dein problem könnte in dem daten-desgn liegen. aber dafür wäre es hilfreich, wenn du noch mal genauer erklären könntest, was genau du machen willst und wie deine tabellen genau aussehen, spriche welche spalten wofür stehen.

      Ilja

      1. yo,

        Natürlich ist es keine Subtabelle sondern wie Du schon gesagt hast hat die FORM1 zweimal eine 1:N-Beziehung zur F1_SUB_FROM.

        das bereitet mir ein wenig "bauchschmerzen". nach meinen gefühl würde ich sagen, das daten-design noch einmal überdenken. aber deine antwort wird wahrschenlich lauten, das geht nicht. also müssen wir deine abfrage finden.

        Einmal im Feld F1_WERT033 und einmal im Feld F1_WERT119. In der F1_SUB_FORM sind für F1_WERT033 9 Datensätze vorhanden, für F1_WERT119 sind es 6 Datensätze.

        ok, ich gehe mal davon aus, dass du beide abfragen schon einzeln überprüft hast. also die abfrage ohne subselect und dann den subselect alleine.

        Geprüft werden muss, ob aus der Werteliste für F1_WERT033 ein Wert eingetragen werden muss, was auch problemlos funktioniert. Wenn als ANZAHL der Wert 9 selektiert wird, ist kein Wert eingetragen und kann entsprechend ausgewertet werden.

        ich gestehe, ich begreife immer nur sehr langsam. wenn ich dich richtig verstanden habe, dann ist die erste prüfung, ob es beim ersten JOIN genau 9 datensätze in der ergebnisliste gibt. dass alles läßt mich noch einmal auf das daten-design zurückkommen, aber ich wiederhole mich....

        Nun muss ich zusätzlich prüfen, ob für F1_WERT119 der WERT '60' in die F1_SUB_FORM eingetragen ist.

        wenn ich das richtig verstanden habe, dann muss man dafür doch keinen subselect machen, sondern eine einfache bedingung reicht oder habe ich das falsch verstanden, meinst du die anzahl der Join-Datensätze gleich 6 ?

        F1_WERT119 = '60' ???

        Meine Idee war eben das als Subselect abzufragen. Jedoch bekomme ich als Ergebnis immer ANZAHL = 9. Den Teil Subselect ignoriert er völlig.

        der subselect macht auch nichts anderes, so er denn richtig funktioniert, dass er von den 9 Datensätze aus der ersten abfrage durch die bedingung datensätze ausschließt. scheinbar erfüllen aber alle 9 Datensätze die bedinung.

        da ist noch eine sache, die ich nicht verstehe und zwar den einsatz der truncate-funktion.

        truncate('1',0), ist nämlich gleich den wert 1, deswegen könnte man schreiben form1.F1_WERT056 = 1. genauso mit den anderen truncate('60',0), das ist einfach mal 60. warum also die truncate funktionen ?

        was du im subselect also prüfst ist, ob 6 < gefunden datensätze in dem subselect sind. da der subselect aber --> uabhängig <-- von der ersten abfrage ist, sprich nicht korrelierend wird die bedingung eben für alle neun datensätze true sein oder für keinen. deswegen auch kein wunder, dass du zum ergebnis 9 kommst. es geht so nur 9 oder 0. willst du einen bezug haben, musst du einen beuzg in den subselect mit reinbringen und das geht bei gleichnamigen tabellen eben nur über aliasnamen, die ich schon mal erwänht habe. was aber genau prüft nun der subselect.

        er schaut, ob der Join mehr als 6 ergebnisdatensätze findet. der JOIN ist aber nicht unproblematisch, es fehlt wie gesagt der bezug zu der ersten abfrage. ich kann noch nicht ganz sehen, wie er aussieht, da ich mit tabellen, die zweifach miteinander verbunden sind, noch nicht gesehen habe. ich rate mal, dass ein bezug der spalte F1_WERT033 und F1SUB_ID mit rein muss. aber dazu musst du wie gesagt alias-namen verwenden.

        ich hoffe, das geschwafel ist verständlich. ich glaube, ich habe viel blonde locken gequatscht und wenig konkretes....

        Ilja