mixmastertobsi: MySQL Subquery

Hallo,

wie ist es möglich, wenn ich in eine MySQL ABfrage eine Subquery habe, diese bei einer anderen Abfrage erneut zu verwenden, ohne hier erneut diese Subquery ausführen zu müssen.

SELECT (SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1) as lastdate, DATEDIFF(lastdate,'2017-06-21') FROM artikel WHERE id='10'
  1. Tach!

    wie ist es möglich, wenn ich in eine MySQL ABfrage eine Subquery habe, diese bei einer anderen Abfrage erneut zu verwenden, ohne hier erneut diese Subquery ausführen zu müssen.

    Ich glaube, ich verstehe nicht, worauf du hinauswillst. Ich versuch mal die Möglichkeiten aufzuzählen, wiederverwendbaren Code zu schreiben. Ist es das was du wissen möchtest?

    Kopieren - ist kein Wiederverwenden im eigentlichen Sinne, aber einfach.

    Stored Procedures und Stored Functions. Besonders letztere eigenen sich als Subquery-Ersetzung, da sie ein Ergebnis zurückliefern können, so wie es andere Funktionen auch können.

    Prepared Statements, die mit dem (My)SQL-Statement PREPARE als Strings zusammengesetzt werden. Davon ist aber eher abzuraten.

    dedlfix.

  2. Hallo mixmastertobsi,

    wie ist es möglich, wenn ich in eine MySQL ABfrage eine Subquery habe, diese bei einer anderen Abfrage erneut zu verwenden, ohne hier erneut diese Subquery ausführen zu müssen.

    SELECT (SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1) as lastdate, DATEDIFF(lastdate,'2017-06-21') FROM artikel WHERE id='10'
    

    Ein vollständiges Beispiel wäre besser. Deine Query hier ließe sich vollständig ohne Subquery ausdrücken:

    SELECT date, DATEDIFF(date,'2017-06-21') FROM history WHERE history.artikel = 10;
    

    Ggfls noch ein ORDER und ein LIMIT, dafür weiß ich zu wenig über deine Datenstrukturen.

    Ich vermute aber, dass es nicht das ist, was du möchtest. Es sind mehr Informationen notwendig.

    LG,
    CK

    1. OK, das Beispiel war wohl etwas zu "einfach", damit Ihr nachvollziehen könnt, was ich meine.

      Zusammengefasst möchte ich erreichen, dass ich die Subquery nicht nochmals abfragen muss, sondern den Wert von Select bereits verwenden kann.

      Wenn ich die Query so abfrage, bekomme ich einen Fehler, weil er "lastdate" nicht kennt.

      SELECT (SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1) as lastdate, DATEDIFF(lastdate,'2017-06-21') FROM artikel WHERE id='10'
      

      Nun könnte ich natürlich auch es wie folgt schreiben, habe aber zwei mal die selbe Abfrage, was auch wenig Sinn macht. Ich muss das hier als Subquery umsetzen, da ich in der Abfrage noch eine SUM-Funktion für eine andere Tabelle verwende und es dann mit der Summe nicht passen würde.

      SELECT (SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1) as lastdate, DATEDIFF((SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1),'2017-06-21') FROM artikel WHERE id='10'
      
      1. Hallo mixmastertobsi,

        Zusammengefasst möchte ich erreichen, dass ich die Subquery nicht nochmals abfragen muss, sondern den Wert von Select bereits verwenden kann.

        Das habe ich verstanden, aber das geht halt nicht in MySQL. Ob es einen anderen Weg gibt hängt ab von dem ganz konkreten Problem; du könntest z.B. die correlating subquery umformen zu einem JOIN. Aber welcher Lösungsweg wirklich für dich in Frage kommt ist mit den Informationen, die du gegeben hast, für mich nicht erkennbar.

        LG,
        CK

      2. Hallo

        Zusammengefasst möchte ich erreichen, dass ich die Subquery nicht nochmals abfragen muss, sondern den Wert von Select bereits verwenden kann.

        Du willst den in einem SELECT ermittelten Wert in einem weiteren, späteren SELECT benutzen/ihn ihm zuweisen? Dann wäre, wie @dedlfix bereits schrieb, eine Stored Procedure oder Funktion ein Weg, weil man dort Variablen erzeugen und über die Laufzeit der Prozedur benutzen kann.

        SELECT (SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1) as lastdate, DATEDIFF((SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1),'2017-06-21') FROM artikel WHERE id='10'
        

        Ah, wohl doch nicht. Da wir hier von MySQL reden, solltest du den Wert unter dem von dir festgelegten Alias auch für weitere Operationen innerhalb des Query benutzen können.

        SELECT
          (SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1) as lastdate,
          DATEDIFF(lastdate, '2017-06-21')
        FROM artikel WHERE id='10'
        

        Ungetestet!

        Tschö, Auge

        --
        Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
        Toller Dampf voraus von Terry Pratchett
      3. Tach!

        Wenn ich die Query so abfrage, bekomme ich einen Fehler, weil er "lastdate" nicht kennt.

        SELECT (SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1) as lastdate, DATEDIFF(lastdate,'2017-06-21') FROM artikel WHERE id='10'
        

        Ja, die Aliases werden erst nach dem Berechnen hinzugefügt, und meines Wissens nach ist auch die Reihenfolge der Berechnungen der Feldwerte in der SELECT-Klausel nicht garantiert.

        Mir fallen da noch User Defined Variables ein, aber die dürften an demselben Problem leiden, obwohl sie dir keinen Syntaxfehler liefern. Beachte dazu die Aussagen im Handbuch.

        SELECT (SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1) as lastdate, DATEDIFF((SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1),'2017-06-21') FROM artikel WHERE id='10'
        

        Eine Lösung wäre, die Query erstmal ohne den DATEDIFF-Teil zu notieren. Dann erstellst du eine zweite Query, die diese Query als Subquery in den FROM-Teil bekommt. (Ja, das ergibt verschachtelte Subquerys.) Im Select-Teil kannst du dann einerseits lastdate aufführen, als auch in einem zweiten Feld deine Berechnung damit durchführen.

        Anmerkung: Wenn du da lediglich ein LIMIT ohne eine Sortierung verwendest, dann ist nicht garantiert, dass du jedes Mal denselben Wert bekommst, sondern den, der zufälligerweise als erstes steht.

        dedlfix.

        1. Edit - wir sind heute die Parallelposter des Tages 😂

          Rolf

      4. Das geht mit einer geschachtelten Query. Hatte ich Dir das nicht neulich bei der EK-Rechnerei sogar als Beispiel gegeben?

        Zum Aufwärmen nochmal die Abfrage ohne DATEDIFF. Da kommt nur ein einziger Wert bei heraus. Damit die Subquery nicht ganz so sinnlos ist, nehme ich an, dass Du auch noch ein paar Spalten (id und ek) aus der Artikel-Tabelle mitnehmen willst. Andernfalls kannst Du auch die history-Tabelle allein abfragen.

        SELECT id, ek, (SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1) as lastdate
        FROM artikel
         WHERE id='10'
        

        Stell Dir nun vor, du hättest eine Tabelle HUGO mit den Spalten ID, EK, LASTDATE und genau einer Zeile. Dein DateDiff sähe dann so aus:

        SELECT id, ek, lastdate, datediff(lastdate, '2017-06-21') FROM hugo
        

        Statt der Table hugo nehmen wir nun die Abfrage von oben - eine SELECT Abfrage kann die Stelle einer Table einnehmen.

        SELECT L.id, L.ek, L.lastdate, datediff(L.lastdate, '2017-06-21')
        FROM (SELECT id, ek, (SELECT date FROM history WHERE history.artikel=artikel.id LIMIT 1) as lastdate
              FROM artikel
              WHERE id='10') hugo
        

        Table-Expressions im FROM brauchen immer einen Alias, darum steht der Hugo noch da. Habe ich jetzt nicht in der DB getestet, nur hier getippt, müsste aber so funzen.

        Rolf