matthias: left join ??

Hallo,

ich habe (verkürztes Beispiel) zwei Tabellen "Fahrer" und "Auto" sowie eine Relation "FahrerAuto".

"Auto":

ID | Name
---------
1  | Audi
2  | Benz
3  | BMW
4  | VW

"Fahrer"

ID | Name
---------
1  | Müller
2  | Meier

"FahrerAuto"
FahrerID | AutoID
-----------------
1        | 1
1        | 2
2        | 2
2        | 3

Nun möchte ich alle Autos angezeigt bekommen, die der Fahrer 1 (Müller) nocht nicht fährt. Das ist hier Auto 3(BMW) und Auto 4(VW).

Mein Versuch war:
SELECT Auto.Name FROM Auto LEFT JOIN FahrerAuto ON Auto.ID = FahrerAuto.AutoID WHERE FahrerAuto.FahrerID != 1 OR FahrerAuto.AutoID IS NULL

ohne die Bedingung " FahrerAuto.FahrerID != 1 OR " liefert mir mysql nur Auto 4 - weil das nicht in der Relation steht. Mit dieser Bedingung bekomme ich aber Auto 3, Auto 4 UND Auto 2 (welches ich aber nicht will) - weil Fahrer 2 dieses Auto fährt.

Meine anderen Versuche sind bislang auch gescheitert. Kennt jemand eine Lösung?

Matthias

  1. Halihallo matthias

    Nun möchte ich alle Autos angezeigt bekommen, die der Fahrer 1 (Müller) nocht nicht fährt. Das ist hier Auto 3(BMW) und Auto 4(VW).

    Dazu brauchst du keinen LEFT OUTER JOIN. Subtrahiere einfach die Menge (alle Autos) mit
    der Menge (Autos, die Fahrer 1 (Müller) fährt). Stichwort: MINUS und Subtraktion von
    Mengen, informiere dich dazu in der Doku deiner RDBMS.

    Viele Grüsse

    Philipp

    --
    RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
    Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
    1. Hallo Philipp,

      Subtrahiere einfach die Menge (alle Autos) mit

      der Menge (Autos, die Fahrer 1 (Müller) fährt). Stichwort: MINUS und Subtraktion von
      Mengen, informiere dich dazu in der Doku deiner RDBMS.

      »»
      das hiesse doch sowas wie:
      SELECT auto.id FROM auto
       - MINUS -
      SELECT fahrerauto.autoID FROM fahrerauto WHERE fahrerauto.fahrerID = 1

      ich benutze leider MySQL 3.2. Da gibts wohl sowas wie MINUS nicht. Und auch keine geschachtelten Select-Statements.. (Ärger)

      Matthias

      1. Halihallo Matthias

        ich benutze leider MySQL 3.2. Da gibts wohl sowas wie MINUS nicht. Und auch keine geschachtelten Select-Statements.. (Ärger)

        Stimmt. Ich glaube das dieses Problem mit MySQL 3.2 in einem Query nicht zu lösen ist.
        Wohl aber mit zwei queries, welche du über eine Programmiersprache selber "verbindest".
        Hast du diese Möglichkeit?

        Viele Grüsse

        Philipp

        --
        RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
        Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
        1. Hallo Philipp,

          Wohl aber mit zwei queries, welche du über eine Programmiersprache selber "verbindest".
          Hast du diese Möglichkeit?

          Ja, mit PHP, ich hole die Ergebnisse der Queries, schreibe beide in seperate Arrays und mache eine Array-Differenz aus beiden. Das geht dann schon, ist aber nicht gerade sehr performant (um nicht zu sagen - *****langsam). Wie gesagt, ist das oben ja nur ein Beispiel, weil es viiiel mehr Daten gibt...

          Viele Grüsse Matthias

          1. Halihallo Matthias

            Ja, mit PHP, ich hole die Ergebnisse der Queries, schreibe beide in seperate Arrays und mache eine Array-Differenz aus beiden. Das geht dann schon, ist aber nicht gerade sehr performant (um nicht zu sagen - *****langsam). Wie gesagt, ist das oben ja nur ein Beispiel, weil es viiiel mehr Daten gibt...

            Meiner Meinung nach der falsche Ansatz. Du selektierst zuerst alle auto_id, welche der
            Lenker 1 fährt (dies dürften weniger sein, als wenn du alle selektierst, die eben von
            anderen Lenkern gefahren werden, somit hast du hier schon eine Reduktion der Eingabe-
            Datenmenge). Diese kleine Anzahl auto_id's selektierst du negativ (NOT) über die Auto-
            Tabelle, alla

            SELECT     name
               FROM    auto
               WHERE   id NOT IN ([liste-mit-auto_ids])

            Dies dürfte ziemlich performant und speicherschonend sein.

            Viele Grüsse

            Philipp

            --
            RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
            Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
            1. Hallo Philipp,

              SELECT     name
                 FROM    auto
                 WHERE   id NOT IN ([liste-mit-auto_ids])

              Vielen Dank für den Tip. Das geht wirklich gleich schneller :)

              Viele Grüsse Matthias

              P.S. ich war grade dabei mir die neue Version von MySQL auf meine SuSE 8.2 zu spielen. Dort gibt es Subselects. Damit habe ich noch nicht gearbeitet. Wie müsste dort - im Prinzip - so ein Statement aussehen? So vielleicht: "SELECT * FROM Auto WHERE auto.id NOT IN(SELECT * FROM fahrerauto WHERE  fahrer = 1)" ?? Kann ich leider noch nicht überprüfen, da SuSE mit der neuen Version noch nicht klarkommt.

              1. use Mosche;

                P.S. ich war grade dabei mir die neue Version von MySQL auf meine SuSE 8.2 zu spielen. Dort gibt es Subselects. Damit habe ich noch nicht gearbeitet. Wie müsste dort - im Prinzip - so ein Statement aussehen? So vielleicht: "SELECT * FROM Auto WHERE auto.id NOT IN(SELECT * FROM fahrerauto WHERE  fahrer = 1)" ?? Kann ich leider noch nicht überprüfen, da SuSE mit der neuen Version noch nicht klarkommt.

                Jedenfalls bei anderen Datenbanken funktioniert es so (Postgres zB).

                use Tschoe qw(Matti);

                --
                  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
                1. Hallo,

                  "SELECT * FROM Auto WHERE Auto.id NOT IN(SELECT * FROM fahrerauto WHERE  fahrerID = 1)"

                  So hab ichs nun ausprobiert.Und bekomme Fehlermeldungen.

                  Jedenfalls bei anderen Datenbanken funktioniert es so (Postgres zB).

                  Dann muss ich nun auf Postgres umsteigen??

                  Funktioniert mit Postgres auch die PHP-Anbindung so reibungslos wie MySQL?

                  Viele Grüsse Matthias

                  1. Hallo Matthias,

                    "SELECT * FROM Auto WHERE Auto.id NOT IN(SELECT * FROM fahrerauto WHERE  fahrerID = 1)"
                    So hab ichs nun ausprobiert.Und bekomme Fehlermeldungen.

                    Dann versuch's mal so:
                    SELECT * FROM Auto WHERE Auto.id NOT IN(SELECT autoID FROM fahrerauto WHERE  fahrerID = 1)

                    Select * in der zweiten Abfrage liefert Dir ja die Werte (autoID, fahrerID) aus fahrerauto, in der Liste willst Du aber nur die AutoID haben.

                    Grüße
                    Andreas

                    --
                    Hier könnte Ihre Werbung stehen.
  2. Hi Matthias

    Mein Versuch war:
    SELECT Auto.Name FROM Auto LEFT JOIN FahrerAuto ON Auto.ID = FahrerAuto.AutoID WHERE FahrerAuto.FahrerID != 1 OR FahrerAuto.AutoID IS NULL

    ohne die Bedingung " FahrerAuto.FahrerID != 1 OR " liefert mir mysql nur Auto 4 - weil das nicht in der Relation steht. Mit dieser Bedingung bekomme ich aber Auto 3, Auto 4 UND Auto 2 (welches ich aber nicht will) - weil Fahrer 2 dieses Auto fährt.

    Das müsste klappen (ungetestet):

    SELECT Auto.Name
      FROM Auto
        LEFT JOIN FahrerAuto
          ON (Auto.ID = FahrerAuto.AutoID
              AND FahrerAuto.FahrerID = 1)
      WHERE FahrerAuto.FahrerID IS NULL

    FahrerAuto.FahrerID = 1 muss in die Join-Klausel mit rein, damit nur solche verbunden werden und du für alle anderen NULL kriegst, sonst passiert genau das was dein Problem war.

    Gruss Daniela

    --
    Nein, wir frieren unsere Hühner nicht auf Gletschern fest.
    Selfcode: sh:) fo:) ch:) rl:) br:> n4:| ie:{ mo:) va:) de:] zu:} fl:( ss:) ls:&