Helmuth: falsches Ergebnis bei Mehrfach-Join

Hallo,

ich hab ja schon letztens die JOIN und fortgeschrittene JOINS Artikel gelesen, aber ich hab schon wieder eine Abfrage bei der ich nicht weiterkomm :o(

Zu den Daten aus Stammdaten (user_id, firmenname, etc.) soll für den jeweiligen User die Anzahl der Anfragen und die Anzahl der Angebote hinzugefügt werden.

Mit einem JOIN funktioniert die Abfrage. Möcht ich die Angebote zusätzlich abfragen, erhalte ich ein falsches Ergebnis. Nämlich das Produkt von Anfragen x Angebote!? Also bei 3 Anfragen und 2 Angeboten steht im Ergebnis 2 mal 6!

SQL-Befehl:
SELECT bizgap_stammdaten.mitglied_id, firmenname, kontosperre, DATE_FORMAT( lastlogin, '%d.%m.%Y %H:%i:%s' ) AS lastlogin, DATE_FORMAT( anmeldedatum, '%d.%m.%Y %H:%i:%s' ) AS anmeldedatum, COUNT( bizgap_anfragen.anfrage_id ) AS anzahl_anfragen,
COUNT( bizgap_angebote.angebot_id ) AS anzahl_angebote
FROM bizgap_stammdaten
LEFT JOIN bizgap_anfragen
ON bizgap_anfragen.mitglied_id = bizgap_stammdaten.mitglied_id
LEFT JOIN bizgap_angebote
ON bizgap_angebote.mitglied_id = bizgap_stammdaten.mitglied_id
GROUP BY bizgap_stammdaten.mitglied_id
ORDER BY 'bizgap_stammdaten.mitglied_id' ASC
LIMIT 0 , 30

Vielen Dank für eure Hilfe,

Helmuth

  1. Moin!

    Mit einem JOIN funktioniert die Abfrage. Möcht ich die Angebote zusätzlich abfragen, erhalte ich ein falsches Ergebnis. Nämlich das Produkt von Anfragen x Angebote!? Also bei 3 Anfragen und 2 Angeboten steht im Ergebnis 2 mal 6!

    Stimmt, und das muß auch so sein bei deinem Query.

    Stell dir den Vorgang mal Schritt für Schritt vor:

    SELECT bizgap_stammdaten.mitglied_id, firmenname, kontosperre, DATE_FORMAT( lastlogin, '%d.%m.%Y %H:%i:%s' ) AS lastlogin, DATE_FORMAT( anmeldedatum, '%d.%m.%Y %H:%i:%s' ) AS anmeldedatum, COUNT( bizgap_anfragen.anfrage_id ) AS anzahl_anfragen, COUNT( bizgap_angebote.angebot_id ) AS anzahl_angebote

    Du willst "diverse Spalten" wissen...

    FROM bizgap_stammdaten

    ...aus dieser Tabelle...

    LEFT JOIN bizgap_anfragen
    ON bizgap_anfragen.mitglied_id = bizgap_stammdaten.mitglied_id

    ...verknüpft mit dieser Tabelle...

    LEFT JOIN bizgap_angebote
    ON bizgap_angebote.mitglied_id = bizgap_stammdaten.mitglied_id

    ...und dieser Tabelle.

    Lass dir das Ergebnis dieser Verknüpfung mal ausgeben. Denn damit arbeitet auch das GROUP BY weiter.

    GROUP BY bizgap_stammdaten.mitglied_id

    Damit faßt du jetzt identische Mitglieds-IDs zusammen. Eine Auseinanderhaltung von Angeboten und Anfragen ist darin gar nicht angegeben.

    ORDER BY 'bizgap_stammdaten.mitglied_id' ASC
    LIMIT 0 , 30

    Sortieren und limitieren hat optische Reize, aber keine inhaltlich-qualitativen Auswirkungen auf das Ergebnis.

    Es kann durchaus sein, dass du für die Ermittlung der zwei Anzahlen auch zwei Querys machen mußt.

    - Sven Rautenberg

    --
    My sssignature, my preciousssss!
    1. Hallo,

      danke für deine Antwort.

      Wenn ich gerne eine Tabelle ausgeben würde mit den oben angeführten Daten und man soll nach allen Spalten sortieren können (Also Id, Anzahl der Angebote, ...) - wie würdest du das angehen?

      Ich dachte ich join das ganze und kann dann mit ORDER BY die Darstellung beeinflussen. Wenn das nicht geht, gibt es aber vermutlich eine andere Lösung...

      danke,

      Helmuth

      1. Hallo,

        Ich dachte ich join das ganze und kann dann mit ORDER BY die Darstellung beeinflussen. Wenn das nicht geht, gibt es aber vermutlich eine andere Lösung...

        Ein JOIN über drei Tabellen ist hier aber nicht das Gewünschte. Statt einer Erklärung ein Beispiel:

        Tabelle: Stammdaten
        ID      Name
        1       a
        2       b
        3       c
        4       d

        Tabelle: Anfragen
        StdID   Anfrage
        1       a1_1
        1       a1_2
        2       a2_1
        2       a2_2
        3       a3_1

        Tabelle: Angebote
        StdID   Angebot
        1       agb1_1
        1       agb1_2
        2       agb2_1
        3       agb3_1

        Ein
        SELECT Stammdaten.ID, Stammdaten.Name, Anfragen.Anfrage, Angebote.Angebot
        FROM (Stammdaten
        LEFT JOIN Anfragen ON Stammdaten.ID = Anfragen.StdID)
        LEFT JOIN Angebote ON Stammdaten.ID = Angebote.StdID;
        ergibt:
        ID      Name    Anfrage  Angebot
        1       a       a1_1     agb1_1
        1       a       a1_1     agb1_2
        1       a       a1_2     agb1_1
        1       a       a1_2     agb1_2
        2       b       a2_1     agb2_1
        2       b       a2_2     agb2_1
        3       c       a3_1     agb3_1
        4       d

        also alle Stammdaten, wenn möglich verbunden mit den entsprechenden Anfragen und nochmal, wenn möglich, verbunden mit den entsprechenden Angeboten.

        Du willst eher
        SELECT Stammdaten.ID, Stammdaten.Name, (select count(*) from Anfragen where ID=StdID) AS Anfragen, (select count(*) from Angebote where ID=StdID) AS Angebote
        FROM Stammdaten;
        ergibt:
        ID      Name    Anfragen   Angebote
        1       a       2          2
        2       b       2          1
        3       c       1          1
        4       d       0          0

        Wenn also Unterabfragen unterstützt werden, dann so, sonst mit zwei getrennten JOIN-SELECTs.

        viele Grüße

        Axel

        1. Wahnsinn! Hab tausend Dank, funktioniert hervorragend :o)

          Super, Danke!

          lg,

          Helmuth

  2. richtiges Ergebnis bei falschem Mehrfach-Join

    das Ergebnist stimmt für diese Anfrage stimmt doch exakt! :)