oskar: Datenbankabfrage

Auf meinem Rechner läuft eine Datenbank mit mysql. Es existiert eine Tabelle "lieferscheine" mit einem Feld ADDR_ID. Weiter gibt es eine Tabelle "adressen" Mit einem Feld KUNNUM.

Die ADDR_ID aus lieferscheine findet sich in KUNNUM wieder.

Ich muss jetzt alle Namen und Mail-Adressen auflisten, von dennen ein Lieferschein vorhanden ist und z.B nicht eine Mailadresse von web.de.

Wie würde eine entsprechende SQL Anweisung lauten?

  1. was hast du denn schon selber probiert?

  2. Tach!

    Ich muss jetzt alle Namen und Mail-Adressen auflisten, von dennen ein Lieferschein vorhanden ist und z.B nicht eine Mailadresse von web.de.

    Wie würde eine entsprechende SQL Anweisung lauten?

    Das ist nicht die Frage, die ich dir beantworten werde. Aber ich werde dir die Werkzeuge nennen, die ich in einem solchen Fall nehmen würde.

    Als erstes erstelle ich eine Query, die die Haupttabelle befragt, ohne zunächst auf die Lieferscheine zu achten. Wenn die läuft, gehts weiter. Es liest sich so, als ob du aus der Lieferschein-Tabelle nur wissen willst, ob es Datensätze gibt. Für diese Frage erstelle ich in einem solchen Fall eine Query, die erstmal die Lieferscheine für einen bestimmten Kunden auflistet. Diese Query kommt nun zusammen mit einem EXISTS() als weitere Bedingung in die erste Query. Die zweite wird dabei so verändert, dass die feste Kundennummer durch einen Bezug auf das entsprechende Feld der Hauptquery ersetzt wird. Das nenne man dann Correlated Subquery.

    Ein anderer Lösungsweg geht über Joins, aber der vorgenannte mit dem EXISTS() liest sich für mich intuitiver: ... WHERE ... AND EXISTS(zweite query).

    dedlfix.

    1. dedlfix, ich glaube, dass EXISTS() hier nicht nötig ist. Ein innerer Join kümmert sich da automagisch drum.

      1. Tach!

        dedlfix, ich glaube, dass EXISTS() hier nicht nötig ist. Ein innerer Join kümmert sich da automagisch drum.

        Natürlich kann man da und in vielen anderen Situationen auch Joins statt Subquerys verwenden. Aber ich finde Joins zum einen weniger verständlich, und zum anderen weniger testbar. Für einen Join musst du immer eine komplette große Query erstellen und bekommst dann immer ein Ergebnisprodukt aus allen beteiligten Datenmengen. Subquerys kann man recht einfach extrahieren und einzeln testen, ob sie die erwartete Ergebnismenge zurückliefern. Alles was die "andere Datenmenge" betrifft steht in einem Subquery schön beisammen und verteilt sich nicht über die einzelnen Klauseln der Hauptquery.

        Natürlich gibt es auch Situationen, für die eine Subquery-Lösung nicht in Frage kommt. Aber ich finde die Vorteile von Subquery-Lösungen überzeugend genug, um mir bei datenmengenübergreifenden Aufgaben immer als erstes die Frage zu stellen: "(wie) kann man das mit einer Subquery lösen?"

        dedlfix.

        1. Hallo dedlfix,

          Natürlich gibt es auch Situationen, für die eine Subquery-Lösung nicht in Frage kommt. Aber ich finde die Vorteile von Subquery-Lösungen überzeugend genug, um mir bei datenmengenübergreifenden Aufgaben immer als erstes die Frage zu stellen: "(wie) kann man das mit einer Subquery lösen?"

          Inwieweit wäre dies relevant für d(e)i(n)e Artikel

          • <https://wiki.selfhtml.org/wiki/Datenbank/Einführung in Joins>
          • <https://wiki.selfhtml.org/wiki/Datenbank/Fortgeschrittene Jointechniken>

          Bis demnächst
          Matthias

          --
          Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
          1. Oh?!

            Es gibt ein SelfSQL? Wusste ich ja gar nicht. erröt

            1. Hallo Rolf b,

              Es gibt ein SelfSQL? Wusste ich ja gar nicht. erröt

              Nicht wirklich. Die Inhalte sind recht übersichtlich. Also wenn du magst …

              Bis demnächst
              Matthias

              --
              Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
          2. Tach!

            Inwieweit wäre dies relevant für d(e)i(n)e Artikel

            • <https://wiki.selfhtml.org/wiki/Datenbank/Einführung in Joins>
            • <https://wiki.selfhtml.org/wiki/Datenbank/Fortgeschrittene Jointechniken>

            Das sind nicht meine, ich habe sie nur wikisiert. Abgesehen davon, das Wissen um Joins braucht man auch dann noch, wenn man Subquery-Lösungen bevorzugt, und dafür sind sie weiterhin geeignet. Subquerys als Alternative wäre vermutlich Stoff für einen weiteren Artikel, in dem man typische Situationen und mögliche Lösungen vorstellt und vergleicht. Ich würde die beiden Artikel nicht dahingehend erweitern wollen, höchstens mit Querverweisen spicken.

            dedlfix.

            1. Hallo dedlfix,

              Das sind nicht meine, ich habe sie nur wikisiert.

              Stimmt, die Autoren sind Vinzenz bzw. Rouven.

              Abgesehen davon, das Wissen um Joins braucht man auch dann noch, wenn man Subquery-Lösungen bevorzugt, und dafür sind sie weiterhin geeignet.

              Ja, ich wollte die Joins keineswegs verbannen ;-)

              Subquerys als Alternative wäre vermutlich Stoff für einen weiteren Artikel, in dem man typische Situationen und mögliche Lösungen vorstellt und vergleicht. Ich würde die beiden Artikel nicht dahingehend erweitern wollen, höchstens mit Querverweisen spicken.

              Hast du denn Lust und Zeit?

              Bis demnächst
              Matthias

              --
              Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
        2. Wir schweifen für den OP zwar jetzt etwas ab, aber das Thema ist interessant :)

          Was ist eine Subquery? Entweder setze ich sie in der SELECT Klausel ein, um den Wert für eine bestimmte Spalte zu bestimmen. Dann bekomme ich im folgenden Beispiel entweder einen Namen oder NULL.

          SELECT mailadresse, SELECT name FROM personen WHERE personen.id = adressen.pers_id) as Name
          FROM adressen
          

          Kann man machen und wenn man nur eine Spalte hinzu holen will, würde ich diese Lösung auch empfehlen. Ich habe schon selbst Monster-Queries gebaut (auf eine Datawarehouse-Sterntabelle), wo ich 20 solcher Subselects drin hatte.

          Aber was ist, wenn ich zwei Felder aus der Personen Tabelle brauche. Zwei Subqueries? Würde ich ineffizient nennen. Und was ist, wenn ich die Sätze gar nicht will, wo es die pers_id der Adressen nicht in der Personentabelle nicht gibt? (Ja ich weiß, ist im Beispiel sehr unwahrscheinlich.) Einen nachgelagerten IS NULL Test einbauen? Joins sind ein Feature von SQL, auf das die Server optimiert sind, und das sollte man dann auch nutzen. Und ich kann durch INNER JOIN oder RIGHT JOIN entscheiden, ob ich Zeilen ohne Match sehen will oder nicht.

          SELECT adressen.mailadresse, personen.name, personen.gebDat, personen.gender
          FROM adressen RIGHT JOIN personen ON adressen.pers_id = personen.id
          

          Der andere Einsatz von Subqueries ist die Exists-Klausel, ABER da kann ich keine Daten herausholen. Nur auf Existenz prüfen. Für den OP glaube ich daher, dass das nichts hilft (es sei denn, du nutzt EXISTS um die Zeilen auszufiltern, wo die Subquery in der SELECT Zeile keine Daten liefert. Aber DAS wäre nun sehr mühsam und vor allem schreibst Du die Subquery dann zweimal).

          Rolf

          1. Tach!

            Wir schweifen für den OP zwar jetzt etwas ab, aber das Thema ist interessant :)

            Ja, das pasiert hin und wieder. Das ist sozusagen sein Preis für die kostenlose Hilfestellung, dass wir sein Problem zum Anlass nehmen, um uns mit weitergehenden Facetten zu amüsieren. Ich schweife aber auch gern wieder zu ihm hin, wenn er zu seinem Problem weitere konkrete Fragen hat.

            Aber was ist, wenn ich zwei Felder aus der Personen Tabelle brauche. Zwei Subqueries? Würde ich ineffizient nennen.

            Ja, das sind die Fälle, wo die Vorteile der Subquery schnell schwinden. Bei zwei Feldern mag man sich unter Umständen noch dazu durchringen, aber bei mehr gewinnt doch der Join. Hier ist es ja dann auch so, dass man die Datenmengen absichtlich mischen möchte, dafür sind Joins ja erfunden worden.

            Es gibt aber auch genügend Fälle, wo man einfach mal eben nur in die andere Datenmenge schauen möchte, ob da was oder wieviel davon existiert oder auch nicht. Dann muss man nicht Joinen, sich dabei ein kartesischen Produkt einhandeln, das man gar nicht braucht und haben will, um es dann mit Gruppierung oder gar DISTINCT wieder wegzuklopfen. Das sind dann die Situationen, wo der Neuling Hände über dem Kopf zusammenschlagend ins Forum gerannt kommt.

            Und was ist, wenn ich die Sätze gar nicht will, wo es die pers_id der Adressen nicht in der Personentabelle nicht gibt? (Ja ich weiß, ist im Beispiel sehr unwahrscheinlich.) Einen nachgelagerten IS NULL Test einbauen?

            Wenn ich dein Beispiel richtig interpretiert habe, dann willst du nur wissen, ob was exstiert oder nicht, und das ist ein Fall, der sich hervorragend mit (NOT) EXISTS() ausdrücken lässt.

            Joins sind ein Feature von SQL, auf das die Server optimiert sind, und das sollte man dann auch nutzen. Und ich kann durch INNER JOIN oder RIGHT JOIN entscheiden, ob ich Zeilen ohne Match sehen will oder nicht.

            Ich bin zwar nicht im Nebenberuf DBMS-Abfragen-Optimierer, aber ich kann mir vorstellen, dass im Index nachschauen einfacher ist, als erst eine gemeinsame Datenmenge zu erzeugen. Das ist jedoch vermutlich das, was der Optimizer umgeht. Warum sollte man das DBMS dann erst damit beauftragen? Es ist semantisch nicht als das ausgedrückt, was man eigentlich will und der Optimizer führt es (gemutmaßt) auch nicht so aus. Also warum dann diesen Weg gehen? Wie gesagt, ich kenne die Arbeitsweise des Optimizers nicht weiter und kann mit dem Gedankengang auch ganz gehörig neben der Realität liegen.

            Der andere Einsatz von Subqueries ist die Exists-Klausel, ABER da kann ich keine Daten herausholen. Nur auf Existenz prüfen.

            Ja, wenn genau das mein Ziel ist, nehme ich das genau dafür.

            Für den OP glaube ich daher, dass das nichts hilft (es sei denn, du nutzt EXISTS um die Zeilen auszufiltern, wo die Subquery in der SELECT Zeile keine Daten liefert. Aber DAS wäre nun sehr mühsam und vor allem schreibst Du die Subquery dann zweimal).

            Das "von dennen ein Lieferschein vorhanden ist und z.B nicht eine Mailadresse von web.de." klingt mir doch genau nach einem EXISTS und einem NOT EXISTS. Wobei ich den zweiten Teil nicht so richtig einzuordnen in der Lage bin. Dazu fehlt mir das Wissen um seine Tabellenstruktur(en). Letzeres ist zudem ein Grund, warum ich auch nur in der Lage bin, eine theoretische Antwort zu geben, selbst wenn ich sie als SQL-Statement formuliert hätte.

            dedlfix.

  3. Hallo Oskar,

    bitte entschuldige die Zugeknöpftheit der bisherigen Antworten, aber es hat schon genug Fragesteller gegeben, die sich auf diese Weise ihre Hausaufgaben machen lassen wollten und dagegen hat sich eine gewisse Allergie entwickelt. Deine Frage ist eine typische Fragestellung, die ein Lehrer Schülern vorsetzt, daher die Reaktion. Die Query eigenständig aufstellen zu können ist ein wichtiger Lernschritt, den kann dir keiner abnehmen.

    Um die SELECT Klausel schreiben zu können, müsste man wissen, in welcher Tabelle der Name und die Mailadresse stehen und wie die Felder heißen. Dann kannst Du unter FROM einen inneren Join der Tables machen, mit ADDR_ID = KUNNUM als Join-Bedingung, und im WHERE Bereich filterst Du die unerwünschten Mailadressen heraus. Wenn Du die Adressen eines bestimmten Providers nicht willst, würde ich Dir einen NOT LIKE Vergleich empfehlen.

    Versuch mal damit einzusteigen, und wenn es nichts wird, dann zeig uns die Query die Du gebaut hast und die der gewünschten Lösung am nächsten kommt.

    Wenn Dir diese Begriffe alle nichts sagen sollten, empfehle ich Dir, dein SQL Studium in einem allgemeinen SQL Tutorial zu beginnen (oder in den Unterrichtsmaterialien, falls Du ein Schüler/Student bist). Tutorials gibt es, aber leider nicht im SelfHTML Wiki. Google mal danach, wirst schon was finden. Empfehlen kann ich nichts, weil ich keins gebraucht habe (nicht weil ich ein Spontangenie wäre, sondern SQL im Studium gelernt habe).

    Gruß Rolf