Q.: Umschreiben eines Subquerys?

Hi,

leider verwendet mein Provider MySQL 4.0.27, damit ist es anscheinend nicht möglich, Subquerys auszuführen.

Ich habe in Bezug auf eine früher von mir gestellte Frage (https://forum.selfhtml.org/?t=163062&m=1061763) eine Abfrage "gestrickt" (von der ich nichtmal weiß, ob sie funktionieren würde), die auf meine mysql-Version umgeschrieben werden müsste.

Frage 1: Ist die Anweisung überhaupt korrekt?
Frage 2: Gibts ne Möglichkeit, sie so umzuformulieren, dass sie auf MySQL 4.0.27 läuft?

SELECT Ampelfarbe, COUNT(*) FROM tabelle_Bewertungen where SpielerID IN
(SELECT SpielerID, COUNT(*) AS n FROM tabelle_Bewertungen GROUP BY SpielerID order by n desc LIMIT 0, 1)
GROUP BY Ampelfarbe

Grüße, Q.

  1. SELECT Ampelfarbe, COUNT(*) FROM tabelle_Bewertungen where SpielerID IN
    (SELECT SpielerID, COUNT(*) AS n FROM tabelle_Bewertungen GROUP BY SpielerID order by n desc LIMIT 0, 1)
    GROUP BY Ampelfarbe

    Zu 1: War nicht ganz korrekt,

    versuch es mal so:

    SELECT Ampelfarbe, COUNT(*) FROM tabelle_Bewertungen where SpielerID IN
    (SELECT SpielerID FROM tabelle_Bewertungen GROUP BY SpielerID)
    GROUP BY Ampelfarbe

    1. SELECT Ampelfarbe, COUNT(*) FROM tabelle_Bewertungen where SpielerID IN
      (SELECT SpielerID, COUNT(*) AS n FROM tabelle_Bewertungen GROUP BY SpielerID order by n desc LIMIT 0, 1)
      GROUP BY Ampelfarbe

      Zu 1: War nicht ganz korrekt,

      versuch es mal so:

      SELECT Ampelfarbe, COUNT(*) FROM tabelle_Bewertungen where SpielerID IN
      (SELECT SpielerID FROM tabelle_Bewertungen GROUP BY SpielerID)
      GROUP BY Ampelfarbe

      Hallo,

      hm. Aber Deine Abfrage produziert doch gar nicht das von mir gewünschte Ergebnis?? Und eine Subquery (die ich vor Mysql 4.1 nicht nutzen darf) ist auch noch enthalten??

      Grüße, Q.

  2. n'abend,

    leider verwendet mein Provider MySQL 4.0.27, damit ist es anscheinend nicht möglich, Subquerys auszuführen.

    der Umstieg von 4.0 auf 4.1 bedeutet Aufwand. Nicht nur für den Provider, sondern vor allem auch für die Kunden, mit ihren Systemen. MySQL 4.1 kann zwar mehr, macht aber auch einige Sachen etwas anders. Das bedeutet es ist nicht 100% abwärtskompatibel. Ähnlich verhält es sich auch mit der PHP4 / PHP5 Umstellung, die noch immer nicht flächendeckend vollzogen wurde.

    Ich habe in Bezug auf eine früher von mir gestellte Frage (https://forum.selfhtml.org/?t=163062&m=1061763) eine Abfrage "gestrickt" (von der ich nichtmal weiß, ob sie funktionieren würde), die auf meine mysql-Version umgeschrieben werden müsste.

    Da musst du selbst Hand anlegen, und 2 Queries draus machen. In der ersten ermittelst du den gewünschten Spieler (die SpielerID reicht ja zur Identifizierung aus), in der zweiten Query holst du dann die benötigten Daten. Beispielsweise so:

    $res = mysql_query( 'SELECT SpielerID FROM table WHERE bedingung = true' );  
    $SpielerID = mysql_fetch_row($res);  
    $SpielerID = $SpielerID[0];  
      
    $res = mysql_query( 'SELECT daten FROM table WHERE SpielerID = '. $SpielerID );  
    while( $row = mysql_fetch_assoc( $res ) )  
      print_r( $row );  
    
    

    SELECT Ampelfarbe, COUNT(*) FROM tabelle_Bewertungen where SpielerID IN

    (SELECT SpielerID, COUNT(*) AS n FROM tabelle_Bewertungen GROUP BY SpielerID order by n desc LIMIT 0, 1)
    GROUP BY Ampelfarbe

      
    
    > Frage 1: Ist die Anweisung überhaupt korrekt?  
      
    Vermutlich wird das nicht funktionieren, weil du in der SubQuery zwei(!) Datenfelder Selektierst (also ein Tupel zurückgibst), in der äußeren Query aber nur ein einzelnes Datenfeld erwartest / prüfst.  
      
    »LIMIT 0, 1« kannst du auch durch »LIMIT 1« ersetzen.  
      
    
    > Frage 2: Gibts ne Möglichkeit, sie so umzuformulieren, dass sie auf MySQL 4.0.27 läuft?  
      
    siehe obiges Beispiel.  
      
    weiterhin schönen abend...
    
    -- 
    #selfhtml hat ein Forum?  
      
    sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|
    
    1. Da musst du selbst Hand anlegen, und 2 Queries draus machen. In der ersten ermittelst du den gewünschten Spieler (die SpielerID reicht ja zur Identifizierung aus), in der zweiten Query holst du dann die benötigten Daten. Beispielsweise so:

      $res = mysql_query( 'SELECT SpielerID FROM table WHERE bedingung = true' );

      $SpielerID = mysql_fetch_row($res);
      $SpielerID = $SpielerID[0];

      $res = mysql_query( 'SELECT daten FROM table WHERE SpielerID = '. $SpielerID );
      while( $row = mysql_fetch_assoc( $res ) )
        print_r( $row );

      
      >   
        
        
      Hi Globe,  
        
      Werd ich gleich umsetzen. Erstmal was essen ;-)  
        
        
        
      
      >   
      > > Frage 1: Ist die Anweisung überhaupt korrekt?  
      >   
      > Vermutlich wird das nicht funktionieren, weil du in der SubQuery zwei(!) Datenfelder Selektierst (also ein Tupel zurückgibst), in der äußeren Query aber nur ein einzelnes Datenfeld erwartest / prüfst.  
      >   
      > »LIMIT 0, 1« kannst du auch durch »LIMIT 1« ersetzen.  
        
        
        
        
      Hab übrigens auf MySQL 5 aufgerüstet und bekomme folgendes:  
        
       MySQL meldet:  
        
      This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'  
        
        
      Verstehe aber Deinen Einwand, dass ich keinen Tulpel brauchen kann, wenn ein eindeutige Zuweisung erforderlich ist.  
        
      Vielen Dank mal wieder, Q.  
        
        
        
        
        
      
      >   
      > > Frage 2: Gibts ne Möglichkeit, sie so umzuformulieren, dass sie auf MySQL 4.0.27 läuft?  
      >   
      > siehe obiges Beispiel.  
      >   
      > weiterhin schönen abend...
      
      1. n'abend,

        Hab übrigens auf MySQL 5 aufgerüstet und bekomme folgendes:

        MySQL meldet:

        This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

        Tja, das ist der alt-bekannte Hut. MySQL kann die Ergebnismenge einer SubQuery (aus welchen Gründen auch immer) nicht LIMITieren. Zugegebenermaßen stellt das (zumindest für mich) ein ziemliches Problem dar. Ich habe zwar eine Lösung, bin mir aber ziemlich sicher, dass es nicht die schönste ist:

        SELECT b.SpielerID, b.Ampelfarbe, COUNT(*) as Gewicht  
        FROM (  
          SELECT SpielerID  
          FROM tabelle_Bewertungen  
          GROUP BY SpielerID  
          ORDER BY COUNT(*) DESC  
          LIMIT 1  
        ) as t  
        JOIN tabelle_Bewertungen b  
          ON ( b.SpielerID = t.SpielerID )  
        GROUP BY b.SpielerID, b.Ampelfarbe
        

        In SubQueries können wir kein LIMIT benutzen, in "Relationen-Queries" hingegen schon. Wir suchen also den einen Benutzer mit den meisten Bewertungen, damit wir mit der SpielerID wieder auf die Bewertungen zugreifen können, um die Gewichte der Ampelfarben zu ermitteln.

        weiterhin schönen abend...

        --
        #selfhtml hat ein Forum?
        sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|
        1. n'abend,

          In SubQueries können wir kein LIMIT benutzen, in "Relationen-Queries" hingegen schon.

          Mittlerweile habe ich auch herausgefunden, warum das so ist. Eine SubQuery in der FROM Klausel, ist in dem Sinne keine SubQuery, sondern mehr ein temporärer View. Also ein View, der zur Laufzeit angelegt wird, statt im System registriert und dadurch wie eine normale Tabelle ansprechbar zu sein. </HinweisAmRande>

          weiterhin schönen abend...

          --
          #selfhtml hat ein Forum?
          sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|
          1. Hi Globe,

            was ist denn das für'n Query??
            Funktioniert phänomenal!!

            Gehen wir mal gemeinsam an die Erklärung heran?

            SELECT b.SpielerID, b.Ampelfarbe, COUNT(*) as Gewicht

            1.Teil der Abfrage aus einer durch nachfolgende Subquery gebildete "virtuelle Tabelle"??

            FROM (
              SELECT SpielerID
              FROM tabelle_Bewertungen
              GROUP BY SpielerID
              ORDER BY COUNT(*) DESC
              LIMIT 1
            ) as t

            Die Subquery ist eine "virtuelle Tabelle? Und "limit" tuts, weil es in der from-Anweisung steht? Die virtuelle Tabelle hat den Alias "t"?

            JOIN tabelle_Bewertungen b
              ON ( b.SpielerID = t.SpielerID )
            GROUP BY b.SpielerID, b.Ampelfarbe

            
            >   
              
            2\. Teil der Abfrage, sowie entsprechende Gruppierung?  
              
              
            Unglaublich. So weit bin ich echt noch lange nicht. Reicht gerade mal, es ansatzweise zu verstehen und zu bestaunen :-)  
              
            Danke, Q.
            
            1. n'abend,

              was ist denn das für'n Query??

              eine, die offenbar funktioniert?

              Funktioniert phänomenal!!

              na dann ist ja gut™

              SELECT b.SpielerID, b.Ampelfarbe, COUNT(*) as Gewicht
              1.Teil der Abfrage aus einer durch nachfolgende Subquery gebildete "virtuelle Tabelle"??

              Jein. Wie du sehen kannst, selektieren wir keine Felder aus der virtuellen Tabelle t. Die Daten stammen allesamt aus der Tabelle tabelle_Bewertungen. Die virtuelle Tabelle missbrauchen wir nur, um sinnvoll einen einzigen Datensatz zu finden (nämlich den mit den meisten Bewertungen). Normalerweise würde ich das in eine SubQuery packen, und nicht in eine virtuelle Tabelle, die ich wiederum gegen meine eigentliche Tabelle joine - aber MySQL bringt das momentan nicht anders.

              FROM (

              SELECT SpielerID
                FROM tabelle_Bewertungen
                GROUP BY SpielerID
                ORDER BY COUNT(*) DESC
                LIMIT 1
              ) as t

              
              > Die Subquery ist eine "virtuelle Tabelle? Und "limit" tuts, weil es in der from-Anweisung steht? Die virtuelle Tabelle hat den Alias "t"?  
                
              Korrekt, die SubQuery ist eine virtuelle Tabelle. virtuelle Tabellen nennt man VIEWs. Im Endeffekt sind Views nichts anderes als SELECT Queries, die man wie eine Tabelle ansprechen kann. Wir sparen uns hier einfach das registrieren der virtuellen Tabelle (mittels CREATE VIEW).  
                
              
              > > ~~~sql
              
              JOIN tabelle_Bewertungen b  
              
              > >   ON ( b.SpielerID = t.SpielerID )  
              > > GROUP BY b.SpielerID, b.Ampelfarbe
              
              
              1. Teil der Abfrage, sowie entsprechende Gruppierung?

              Genau, hier verknüpfen (joinen) wir den einen Datensatz aus der virtuellen Tabelle mit allen Datensätzen aus tabelle_Bewertungen, bei denen die SpielerID übereinstimmt. Im Endeffekt holen wir uns hier die Daten eines bestimmten Spielers.

              Die Gruppierung brauchen wir, damit wir die Ampelfarben aggregieren können.

              Unglaublich. So weit bin ich echt noch lange nicht. Reicht gerade mal, es ansatzweise zu verstehen und zu bestaunen :-)

              Beschäftige dich ein paar Jahre mehr oder minder intensiv mit dem Thema, dann schaut die Welt ganz anders aus. Keinem von uns sind Erfahrungen und Kenntnisse einfach so in den Schoß gefallen. Beruhigenderweise wird das bei dir auch nicht anders sein ;)

              weiterhin schönen abend...

              --
              #selfhtml hat ein Forum?
              sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|
              1. was ist denn das für'n Query??

                eine, die offenbar funktioniert?

                Nunja...

                ...

                ...

                ...

                Jep! Sooo isses *g* :-))

                Funktioniert phänomenal!!

                na dann ist ja gut™

                :-)

                Jein. Wie du sehen kannst, selektieren wir keine Felder aus der virtuellen Tabelle t. Die Daten stammen allesamt aus der Tabelle tabelle_Bewertungen. Die virtuelle Tabelle missbrauchen wir nur, um sinnvoll einen einzigen Datensatz zu finden (nämlich den mit den meisten Bewertungen).

                Ok. Verstanden.

                Korrekt, die SubQuery ist eine virtuelle Tabelle. virtuelle Tabellen nennt man VIEWs. Im Endeffekt sind Views nichts anderes als SELECT Queries, die man wie eine Tabelle ansprechen kann. Wir sparen uns hier einfach das registrieren der virtuellen Tabelle (mittels CREATE VIEW).

                Wieder was gelernt. Views. Create View. 2 Begriffe, die ich nicht kannte, aber jederzeit wieder erkenne.

                Beschäftige dich ein paar Jahre mehr oder minder intensiv mit dem Thema, dann schaut die Welt ganz anders aus. Keinem von uns sind Erfahrungen und Kenntnisse einfach so in den Schoß gefallen. Beruhigenderweise wird das bei dir auch nicht anders sein ;)

                Puh. Dein Wort in Gottes Gehörgang. Ich freu mich ja wirklich um jede erlernte Technick, Methode usw. Aber ab und an hab ich doch das Gefühl, daß die Lücken, Differenzen, Unterschiede zu denen, die das "drauf haben" noch sehr, sehr groß sind. Aber das muß wohl so sein...

                Grüße, Q.

                weiterhin schönen abend...

                1. n'abend,

                  Wieder was gelernt. Views. Create View. 2 Begriffe, die ich nicht kannte, aber jederzeit wieder erkenne.

                  du kannst damit ja mal ein wenig experimentieren.

                  Lege dir eine Tabelle an und fülle sie mit irgendwelchen Daten. Z.b. den beiden Feldern »name« und »status«. Du könntest einen View anlegen, der nur die Namen kennt, deren Status = 1 ist:

                  CREATE VIEW testview AS  
                    SELECT name as bezeichnung  
                    FROM table  
                    WHERE status = 1;
                  

                  Damit haben wir bereits 2 Dinge gezeigt:
                  (1) wir können die Ergebnismenge eines Views beeinflussen
                  (2) wir können die Felder beeinflussen, die ein View enthalten kann

                  SELECT * FROM testview wird dir dann nur die Datensätze (bzw. eigentlich nur die »namen« Felder) ausgeben, deren Status = 1 ist.

                  Du kannst beliebig komplexe Queries als Views "sichern", wenn das für deine Applikation sinnvoll erscheint. Du kannst Views wie Tabellen ansprechen, sie joinen, darauf Selektieren und beliebig kaskadieren.

                  In einem meiner Projekte arbeite ich mit versionierten Datensätzen. Sprich ich kenne in dem Sinne kein UPDATE, sondern speichere jeden Datensatz neu ab und merke mir die Zeit, zu der ich die Änderung vollzogen hab. Es ist ziemlich mühselig in jeder einzelnen Abfrage darauf zu achten, dass ich den gerade aktuellen Datensatz bekomme. Also habe ich die Query, die mir den neusten Datensatz liefert als View "gespeichert". (Um mal eine sinnvolle Anwendung von Views zu nennen)

                  Puh. Dein Wort in Gottes Gehörgang. Ich freu mich ja wirklich um jede erlernte Technick, Methode usw. Aber ab und an hab ich doch das Gefühl, daß die Lücken, Differenzen, Unterschiede zu denen, die das "drauf haben" noch sehr, sehr groß sind. Aber das muß wohl so sein...

                  Ich habe im Jahre des Herrn 98 mit "Webentwicklung" (*hust*) angefangen. Du kannst versichert sein, dass ich nicht bei #selfhtml rumhänge um mit nicht vorhandenem Wissen zu protzen, sondern das Wissen der anderen aufzusaugen ;)

                  weiterhin schönen abend...

                  --
                  #selfhtml hat ein Forum?
                  sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|
                  1. du kannst damit ja mal ein wenig experimentieren.

                    Hi Globe,

                    genau DAS habe ich gestern mal gemacht. Und zwar an einem meiner früheren "Projekte". Hat prima geklappt. In meinem Fall war es zwar jetzt kei9ne wirklich Erleichterung, statt der Abfrage einen View zu erzeugen, aber ich denke, ich habe verstanden, worum es geht.

                    Dank Dir :-)

                    Q.

      2. $res = mysql_query( 'SELECT SpielerID FROM table WHERE bedingung = true' );

        $SpielerID = mysql_fetch_row($res);
        $SpielerID = $SpielerID[0];

        $res = mysql_query( 'SELECT daten FROM table WHERE SpielerID = '. $SpielerID );
        while( $row = mysql_fetch_assoc( $res ) )
          print_r( $row );

          
        entspricht:  
        SELECT tb1.\* FROM table\_a tb1, table\_b tb2 WHERE tb2.SpielerID = tb1.SpielerID AND tb1.bedingung = true;  
        
        
        1. n'abend,

          entspricht:
          SELECT tb1.* FROM table_a tb1, table_b tb2 WHERE tb2.SpielerID = tb1.SpielerID AND tb1.bedingung = true;

          Das Ergebnis ist zwar das gleiche, jedoch die Laufzeit in der Regel nicht.

          weiterhin schönen abend...

          --
          #selfhtml hat ein Forum?
          sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|