Kalle: Syntax bei SELECT ... COUNT mit zwei Tabellen

Hallöle,

ich habe eine Tabelle mit Vereinen und eine andere Tabelle mit Veranstaltungsterminen. Nun möchte ich eine Liste mit ALLEN Vereinen und der Anzahl ihrer Veranstaltungen, auch bei Null Veranstaltungen.

PROBLEM: Beim Folgenden Query bekomme ich nur Vereine, die mindestens eine Veransatltung haben:

SELECT akt_adressen.nr nr, akt_adressen.name1 name, akt_adressen.plz plz, akt_adressen.ort_nr ort_nr, akt_adressen.ort ort, count(*) ct
 FROM akt_adressen
 INNER JOIN termine
 ON (   termine.tag >= '".$tag_von."'
    and termine.tag <= '".$tag_bis."'
    and termine.loe_kz = 0
    and akt_adressen.nr = termine.veranstalter_nr )
 GROUP BY plz, name

Wo liegt mein Denkfehler?

Liebe Grüße aus Worms, Kalle

  1. Halihallo Kalle

    PROBLEM: Beim Folgenden Query bekomme ich nur Vereine, die mindestens eine Veransatltung haben:

    LEFT OUTER JOIN ist dein Freund.

    INNER JOIN termine
    ON (   termine.tag >= '".$tag_von."'
        and termine.tag <= '".$tag_bis."'
        and termine.loe_kz = 0
        and akt_adressen.nr = termine.veranstalter_nr )

    INNER JOIN ... ON (...)

    definiert _nur_ die Join-Bedingung! - Alles was _nicht_ zur Join-
    Bedignung gehört, kommt in die WHERE-Klausel!
    In deinem Beispiel gehört wohl alles ausser
    akt_adressen.nr=termine.veranstalter_nr
    in die WHERE-Klausel. Aber: daran hängt der Fehler sicher nicht, es
    ist eine reine Stil-Bemerkung.

    Viele Grüsse

    Philipp

    1. Hallo Philipp,

      habe den SELECT geändert, aber das Ergebnis ist genau gleich, es fehlen weiterhin die Vereine ohne Termine:

      SELECT akt_adressen.nr nr, akt_adressen.name1 name, akt_adressen.plz plz, akt_adressen.ort_nr ort_nr, akt_adressen.ort ort, count(*) ct
       FROM akt_adressen
       LEFT OUTER JOIN termine
       ON (  akt_adressen.nr = termine.veranstalter_nr )
       WHERE termine.tag >= '".$tag_von."'
       AND   termine.tag <= '".$tag_bis."'
       AND   termine.loe_kz = 0
       GROUP BY plz, name

      Das war also nicht die Lösung.

      Hast du noch einen Tipp?

      Liebe Grüße, Kalle.

      1. Halihallo Kalle

        SELECT akt_adressen.nr nr, akt_adressen.name1 name, akt_adressen.plz plz, akt_adressen.ort_nr ort_nr, akt_adressen.ort ort, count(*) ct
         FROM akt_adressen
         LEFT OUTER JOIN termine
         ON (  akt_adressen.nr = termine.veranstalter_nr )
         WHERE termine.tag >= '".$tag_von."'
         AND   termine.tag <= '".$tag_bis."'
         AND   termine.loe_kz = 0
         GROUP BY plz, name

        Falls es zu einem Verein kein Termin gibt, werden die Attribute des
        Termins mit NULL aufgefüllt. Die Konsequenz ist, dass die WHERE-
        Bedingung nicht mehr zugrifft und _deshalb_ werden diese Vereine
        dennoch nicht selektiert. LEFT OUTER JOIN funktioniert aber :-)

        Vielleicht unterstützt deine Datenbank eine Art

        IS_NULL(termine.id)

        dann könntest du etwa folgende WHERE-Klausel entwerden:

        ... WHERE
          IS_NULL(termine.id) OR
          (
            termine.tag >= '...' AND
            termine.tag <= '...' AND
            termine.loe_kz = 0
          )

        sprich: Entweder der Verein hat gar keinen Termin _oder_ er erfüllt
        alle genannten "Termin-Eigenschaften".

        Das war also nicht die Lösung.

        Ich bringe dir nur Vorschläge. In die Lösung umsetzen, musst du schon
        selber.

        Hast du noch einen Tipp?

        War der mit LEFT OUTER JOIN denn nicht gut?

        Viele Grüsse

        Philipp

        1. yo,

          Die Konsequenz ist, dass die WHERE-
          Bedingung nicht mehr zugrifft und _deshalb_ werden diese Vereine
          dennoch nicht selektiert. LEFT OUTER JOIN funktioniert aber :-)

          wenn mch nicht alles täuscht, dann sollte der optimierer zuerst die bedigungen in den WHERE Klausel überprüfen und dann erst die JOIN Bedingung durchführen.

          Ilja

  2. soweit ich das weiss ist das das NULL problem, dass alle Datensätze die NULL enthalten automatisch falsch sind ?!

    kommentar/hilfe bitte ;-)

    1. da hammers doch: http://www.mysql.de/doc/de/Problems_with_NULL.html

      ich würde die tabelle einfach umstrukturieren und einen default wert zuweisen der nicht NULL ist sondern ''

  3. yo,

    zum einen bekommst du probleme, weil nach der SELECT Klausel nur die spalten erwähnt werden sollten, die auch durch die GROUP BY Klausel gruppiert wurden, mit ausnahme von aggregat funktionen. neuere MySQL Vesionen erlauben zwar solche Konstrukte und schmeissen keine Fehlermeldung aus, das ist aber nicht immer zum vorteil, sondern oft ein rate mal mit rosenthal. insofern würde ich einfach die entsprechenden spalten n der GROUP BY KLausel hinzufügen oder zum Testen erst mal die Spalten in der SELECT Klausel einschränken.

    zum anderen solltest du dich an den rat von phillip halten, LEFT JOIN ist dein freund. aggregatfunktionen wie count() zählen NULL werte nicht mit, was aber eigentlich nicht dein problem sein sollte, da du count(*) anwendest.

    Ilja