Helmut Weber: MySQL-Abfrage

Hallo SelfForum,

ich hänge gerade an einer (wahrscheinlich simplen) SQL-Abfrage:

Ich habe 2 Tabellen. In einer sind die Produkte gespeichert, und in der anderen sind Produkte markiert, die nicht mit ausgegeben werden sollen:

Tabelle 1:
-------------------------------------
| id | best-nr | beschreibung | ... |
-------------------------------------
   |
   -----
       | Tabelle 2:
------------------
| id | pid | ... |
------------------

Mein Versuch:

SELECT id, best-nr, beschreibung FROM tabelle1 tab1, tabelle2 tab2 WHERE tab1.id != tab2.pid

liefert mir die Produkte in Tabelle 1 in x-facher Ausführung (Wahrscheinlich so oft, wie die id nicht in Tabelle 2 vorkommt)

Kann mir jemand einen kleinen Denkanstoss geben?

Gruß
Helmut Weber

--
-------------------------------------------
Mode ist eine Variable, Stil eine Konstante
  1. Hi,

    SELECT id, best-nr, beschreibung FROM tabelle1 tab1, tabelle2 tab2 WHERE tab1.id != tab2.pid

    die Join-Bedingung fehlt.

    liefert mir die Produkte in Tabelle 1 in x-facher Ausführung (Wahrscheinlich so oft, wie die id nicht in Tabelle 2 vorkommt)

    Dieses Phänomen ist absolut symptomatisch dafür.

    Cheatah

    --
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hallo Cheatah,

      SELECT id, best-nr, beschreibung FROM tabelle1 tab1, tabelle2 tab2 WHERE tab1.id != tab2.pid

      die Join-Bedingung fehlt.

      Ich habe folgende SQL-Anweisung aufgebaut:
      SELECT tab1.id, tab1.best-nr, tab1.beschreibung
      FROM tabelle1 tab1
      INNER JOIN tabelle2 tab2
      ON tab1.id != tab2.pid

      So wie es aussieht, habe ich jetzt die gleiche Anweisung in grün erschaffen ;)
      Werde mal versuchen ob ich mit LEFT JOIN zu einem besseren Ergebniss komme, oder bin ich jetzt auf dem Holzweg?

      Gruß
      Helmut Weber

      --
      -------------------------------------------
      Mode ist eine Variable, Stil eine Konstante
      1. Hi,

        die Join-Bedingung fehlt.
        Ich habe folgende SQL-Anweisung aufgebaut:

        prima, Du verknüpfst jeden Datensatz der ersten Tabelle mit jedem der zweiten, bis auf einen.

        Werde mal versuchen ob ich mit LEFT JOIN zu einem besseren Ergebniss komme, oder bin ich jetzt auf dem Holzweg?

        Mit dem "!=" bist Du auf dem Holzweg. Und ich werde nie verstehen, warum es bei MySQL extra Befehle für Joins gibt.

        Cheatah

        --
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
        1. Hallo,

          Das müsste man sich so vorstellen:

          Welche Datensätze sollen aus PRODUKT aussortiert werden?

          select * from PRODUKT where PRODUKT.ID = GESPERRT.ID;

          Und dann müsste man sagen, dass man gerade das Gegenteil davon haben will:

          TEST ist meine Proukt-Datei...

          select * from TEST
          left join GESPERRT on (TEST.ID_TEST = GESPERRT.ID_TEST) where GESPERRT.ID_GESPERRT is NULL order by TEST.ID_TEST;

          Der ursprüngliche Tipp stammte von Daniela Koller:
          http://forum.de.selfhtml.org/archiv/2003/2/37323/#m204537

          Grüße

          Tom

        2. hi

          prima, Du verknüpfst jeden Datensatz der ersten Tabelle mit jedem der zweiten, bis auf einen.

          das ist meienr meinung nach nicht ganz richtig. alle wo der primary und der foreign key gleich sind und das kann mehr als einmal der fall sein (1:n beziehung), es sein den, in der spalte des foreign keys sind keine gleichen einträge erlaubt.

          Ilja

          1. Hi,

            prima, Du verknüpfst jeden Datensatz der ersten Tabelle mit jedem der zweiten, bis auf einen.
            das ist meienr meinung nach nicht ganz richtig. alle wo der primary und der foreign key gleich sind und das kann mehr als einmal der fall sein (1:n beziehung), es sein den, in der spalte des foreign keys sind keine gleichen einträge erlaubt.

            ja. Ich war ursprünglich versucht, von "fast allen der zweiten Tabelle" zu reden, das wäre wohl richtiger gewesen :-)

            Cheatah

            --
            X-Will-Answer-Email: No
            X-Please-Search-Archive-First: Absolutely Yes
            1. hi,

              ja. Ich war ursprünglich versucht, von "fast allen der zweiten Tabelle" zu reden, das wäre wohl richtiger gewesen :-)

              auf jeden fall viel zu viele, die er gar nicht alle haben will. ;-)

              Ilja

        3. Hallo,

          Und ich werde nie verstehen, warum es bei MySQL extra Befehle für Joins gibt.

          Welche meinst Du da?

          viele Grüße

          Axel

          1. Hi,

            Und ich werde nie verstehen, warum es bei MySQL extra Befehle für Joins gibt.
            Welche meinst Du da?

            z.B. "JOIN".

            Cheatah

            --
            X-Will-Answer-Email: No
            X-Please-Search-Archive-First: Absolutely Yes
            1. Hallo,

              Und ich werde nie verstehen, warum es bei MySQL extra Befehle für Joins gibt.
              Welche meinst Du da?

              z.B. "JOIN".

              Das ist aber nichts MySQL spezifisches. Das kommt aus der relationalen Algebra. Mit Where-Klauseln bekommt man eben nur einen INNER JOIN hin. Es würde mich sehr wundern, wenn irgendein relationales DBMS _keine_ explizite JOIN-Syntax hätte.

              Oder meinst Du: "Und ich werde nie verstehen, warum es bei MySQL extra Befehle für Joins gibt, wo sie doch ohnehin kaum von der Hauptgruppe der MSQL-User benutzt werden?"

              Da könnte ich Dir voll zustimmen.

              viele Grüße

              Axel

              1. Hi,

                z.B. "JOIN".
                Das ist aber nichts MySQL spezifisches.

                mag sein, ich finde es trotzdem nicht sinnvoll.

                Mit Where-Klauseln bekommt man eben nur einen INNER JOIN hin.

                Komisch, bei Oracle geht auch der OUTER JOIN mit einer WHERE-Klausel.

                Oder meinst Du: "Und ich werde nie verstehen, warum es bei MySQL extra Befehle für Joins gibt, wo sie doch ohnehin kaum von der Hauptgruppe der MSQL-User benutzt werden?"

                Nein, auch wenn "MSQL" "MySQL" heißen sollte. Bei MySQL kommt erschwerend hinzu, dass es (zumindest bis vor kurzem) noch nicht mal Foreign Key Constraints gab, die in einer über WHERE hinausgehenden Syntax genutzt werden könnten - wobei ich explizit erwähnen möchte, dass eine solche Syntax nicht auf Joins über Foreign Keys beschränken dürfte.

                Cheatah

                --
                X-Will-Answer-Email: No
                X-Please-Search-Archive-First: Absolutely Yes
                1. Hallo,

                  z.B. "JOIN".
                  Das ist aber nichts MySQL spezifisches.

                  mag sein, ich finde es trotzdem nicht sinnvoll.

                  Doch, ich schon. Es besteht ein _Unterschied_ zwischen der relationalen Verbindung von Datensätzen aus Tabellen (join) und den Filterkriterien für Datensätze einer Datensatzmenge (where). Das Vermischen dieser grundsätzlich unterschiedlichen Operationen macht eine Query unübersichtlich, zumal durchaus _beide_ Operationen in _einer_ Query denkbar sind.

                  Mit Where-Klauseln bekommt man eben nur einen INNER JOIN hin.

                  Komisch, bei Oracle geht auch der OUTER JOIN mit einer WHERE-Klausel.

                  Mit diesem komischen (+) Operator? Flag? Wasauchimmer?

                  Offensichtlich kommt auch Oracle so langsam hinter den Unterscheid zwischen JOIN und Filter(WHERE) ;-))

                  http://www.oreillynet.com/pub/a/network/2002/04/23/fulljoin.html
                  <cite>
                  Among several new features, Oracle9i has introduced the ANSI standard join syntax. The new join syntax is not only SQL92 compliant, but it is elegant and makes the outer join syntax more intuitive. The biggest advantage of the new join syntax is its support for full outer joins, which is not directly feasible in Oracle8i. In this article I discuss the full outer join feature of Oracle9i, and provide some examples.
                  </cite>

                  viele Grüße

                  Axel

  2. hi

    Ich habe 2 Tabellen. In einer sind die Produkte gespeichert, und in der anderen sind Produkte markiert, die nicht mit ausgegeben werden sollen:

    warum brauchst du dafür 2 tabellen. arbeite doch mit einem flag in der ersten tabelle, das heißt eine neue spalte, die den wert 0 oder 1 haben kann. 0 steht für gesperrt nicht ausgeben und 1 für frei ausgeben.

    was die 2 tabelen betrifft, so musst du sie richtig miteinander verknüpfen. dafür hälst du dir am besten vor augen, was passiert, wenn du zwei tabellen miteinander verknüpfst und keine datensätze durch eine bedingung ausschließt, in deinem fall also ohne die WHERE tab1.id != tab2.pid. dann würde das sogenante karthesische produkt gebildet:

    jeder datensatz in der ersten tablle wird mit jeden datensatz aus der zweiten datensatz verknüpft.

    sagen wir tabelle eins hat 10 datensätze und tabelle 8 datensätze, dann würdest du bei dir mit SELECT id, best-nr, beschreibung FROM tabelle1 tab1, tabelle2 tab2 10 * 8 = 80 Datensätze herauskommen. nun bringen wir wieder deine where bedingung mit rein. diese schließt aber nur alle datensätze aus, wo sich die beiden id's gleichen, nimmt also alle ungleichen mit rein. das sind noch eine ganze menge.

    Ilja

    1. Hallo Ilja,

      warum brauchst du dafür 2 tabellen. arbeite doch mit einem flag in der ersten tabelle, das heißt eine neue spalte, die den wert 0 oder 1 haben kann. 0 steht für gesperrt nicht ausgeben und 1 für frei ausgeben.

      Die zweite Tabelle habe ich deshalb gewählt, weil zum Einen darin noch weitere Daten gespeichert sind (Auslaufdatum und Ersatzprodukt) und zum Anderen wollte ich dadurch die Datenbank ein wenig gliedern.

      sagen wir tabelle eins hat 10 datensätze und tabelle 8 datensätze, dann würdest du bei dir mit SELECT id, best-nr, beschreibung FROM tabelle1 tab1, tabelle2 tab2 10 * 8 = 80 Datensätze herauskommen. nun bringen wir wieder deine where bedingung mit rein. diese schließt aber nur alle datensätze aus, wo sich die beiden id's gleichen, nimmt also alle ungleichen mit rein. das sind noch eine ganze menge.

      Ich werde also noch ein wenig an meinen Bedingungen experimentieren. In meinem Buch für MySQL ist alles ein wenig besch... erläutert.

      Für kleine Tipps bin ich natürlich sehr Dankbar ;)

      Gruß
      Helmut Weber

      --
      -------------------------------------------
      Mode ist eine Variable, Stil eine Konstante
      1. hi Helmut,

        Für kleine Tipps bin ich natürlich sehr Dankbar ;)

        left join über beide tabelle mit einer NULL prüfung:

        SELECT tab1.* FROM tab1
        LEFT JOIN tab2 ON tab1.id=tab.id
        WHERE tab2.id is NULL

        ohne Garantie, nicht getestet

        gruß
        Ilja

  3. Hallo Helfer,

    vielend Dank für Eure Hilfe!

    Die Tipps von Ilja und Tom haben mich zum Erfolg geführt.

    Jetzt muss ich nur noch das heute gelernte in meinen Hirnwindungen verinnerlichen, um beim nächsten Problem mit JOINS selbst auf die Lösung zu kommen.

    Gruß
    Helmut Weber

    --
    -------------------------------------------
    Mode ist eine Variable, Stil eine Konstante
    1. Hello,

      Jetzt muss ich nur noch das heute gelernte in meinen Hirnwindungen verinnerlichen, um beim nächsten Problem mit JOINS selbst auf die Lösung zu kommen.

      Es reicht ja, wenn man weiß, wo es steht - wie Du siehst. Ich hatte mir das leidr auch nicht merken können.

      Hoffen wir mal, dass der Self-Server gut gepflegt wird.

      Grüße

      Tom

      PS: Für 'nen guten Tipp könnte man doch eigentlich 1Euro überweisen, oder? Ich denk mal drüber nach.

  4. Hallo,

    ich hänge gerade an einer (wahrscheinlich simplen) SQL-Abfrage:

    Ich habe 2 Tabellen. In einer sind die Produkte gespeichert, und in der anderen sind Produkte markiert, die nicht mit ausgegeben werden sollen:

    Tabelle 1:

    | id | best-nr | beschreibung | ... |

    |
       -----

    Tabelle 2:
    id

    Mein Versuch:

    SELECT id, best-nr, beschreibung FROM tabelle1 tab1, tabelle2 tab2 WHERE tab1.id != tab2.pid

    liefert mir die Produkte in Tabelle 1 in x-facher Ausführung (Wahrscheinlich so oft, wie die id nicht in Tabelle 2 vorkommt)

    Genau! Mit einem INNER JOIN geht das nicht.

    SELECT Tabelle1.id, Tabelle1.[best-nr], Tabelle1.beschreibung
    FROM Tabelle1 LEFT JOIN Tabelle2 ON Tabelle1.id = Tabelle2.pid
    WHERE Tabelle2.pid Is Null;

    Left Joins beinhalten _alle_ Datensätze der links stehenden Tabelle, also Tabelle1, und nur die Datensätze aus der rechts stehenden Tabelle, also Tabelle2, bei denen die Inhalte der verknüpften Felder gleich sind. Die Felder der Datensätze aus Tabelle2, die _keine_ Entsprechung in Tabelle1 haben, werden mit NULL als Inhalt dargestellt. Filterst Du also diese NULL-Werte eines Feldes aus Tabelle2 heraus, hast Du alle Datensätze aus Tabelle1, die _keine_ Entsprechung in Tabelle2 haben.

    viele Grüße

    Axel