Bearbeitung und beachtung der Existenz von ID-Gruppen

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Bearbeitung und beachtung der Existenz von ID-Gruppen

    Hallo PHPler und SQLer,

    derzeit versuche ich ein Beispiel aus einem PHP-Buch zu erweitern, was bis zu einem Punkt auch klappte. Es ging um eine WHILE-Schleife, die sich wiederholt, bis ein Wert X 0 ist. Darin integriert ist eine IF-ELSE-Anweisung, die unterscheidet, ob der letzte DB-Eintrag größer oder kleiner X ist.

    Nun aber soll folgendes verändert werden.
    Wo die Datenbank noch aus einem Index id_s und count bestand, wird sie nun um die grp_id erweitert. Die Grp_id ist eine Obergruppe für Count.

    Die Tabelle sähe somit so aus:
    ID_s | Grp_id | Count
    1 - 1 - 50
    2 - 1 - 75
    3 - 1 - 120
    4 - 2 - 90
    5 - 2 - 50
    6 - 3 - 80
    7 - 3 - 90
    8 - 3 - 20

    Folglich liegt die Summe in Gruppe 1 bei 245, bei Gruppe 2 140 und in Gruppe 3 bei 190.

    Jetzt der Code:

    PHP-Code:
    $x 100;
    $last "SELECT count, grp_id, id_s FROM testnull GROUP BY grp_id DESC LIMIT 1";

             
    $result2 mysql_query($last) or die(mysql_error());
             WHILE(
    $row2 mysql_fetch_array($result2))

             {
             
    $count $row2['count'];
             
    $id_s $row2['id_s'];
             
    $grp $row2['grp_id'];
             }

    WHILE (
    $x>0)
             {
             IF (
    $x<$count)
             {
               
    $count $count $x;
               echo 
    "$x ";
               
    $exdel3 "UPDATE testnull SET count = $count WHERE grp_id = $grp_id GROUP BY grp_id DESC LIMIT 1";
               
    $delorder2 mysql_query($exdel3);
               
    $x 0;
             }

             ELSE
             {
               
    $x $x-$count;
               echo 
    "$x ";
               
    $delete "DELETE FROM testnull GROUP BY grp_id DESC LIMIT 1";
               
    $loesch mysql_query($delete);
             }

             } 
    Eigentlich sollte das Ergebnis dann sein:

    ID_s | Grp_id | Count
    1 - 1 - 50
    2 - 1 - 75
    3 - 1 - 20
    4 - 2 - 40
    6 - 3 - 80
    7 - 3 - 10

    Doch statt dessen sieht es dann so aus:

    ID_s | Grp_id | Count
    1 - 1 - 50
    2 - 1 - 75
    3 - 1 - 120
    4 - 2 - 90
    5 - 2 - 50
    6 - 3 - 80
    7 - 3 - 10


    Inzwischen ist mir zwar klar, dass der Gebrauch von Group by keinen Sinn ergeben mag, aber wo mag der Fehler liegen? Ich habe - achtung, Hinweis - bereits in einem Forum nachgefragt (mit dem Hinweis, dass ich mich hier erkundigen werde), leider aber gab es bisher noch keine Lösung.

    Zwar gab es einen Ansatz mit
    PHP-Code:
    $exdel3 "UPDATE testnull SET count = $count  
                    WHERE grp_id = 
    $grp_id
                    AND id_s = 
    $id_s"
    und

    PHP-Code:
    DELETE FROM testnull 
    WHERE grp_id 
    $grp_id
    AND id_s $id_s
    . Dies führte aber leider nicht zum erwarteten Ergebnis trotz einiger Tüftelei.

    Vielleicht hat einer von euch ene Idee.

    Einen Dank im Vorraus,

    krampi

  • #2
    Zitat von krampi Beitrag anzeigen
    Eigentlich sollte das Ergebnis dann sein:

    ID_s | Grp_id | Count
    1 - 1 - 50
    2 - 1 - 75
    3 - 1 - 20
    4 - 2 - 40
    6 - 3 - 80
    7 - 3 - 10
    Erkläre bitte, warum das das Ergebnis sein soll.

    Von einer Gruppierung nach Grp_id ist da nichts zu erkennen. In welcher Art und Weise soll diese „eine Obergruppe für Count“ sein?


    Bitte beschreibe exakt dein Problem.
    Was willst du erreichen?
    Welche Ausgabe erwartest du bei welchen Beispiel-Eingabedaten, und wie soll dieses Ergebnis zustande kommen?


    Und gewöhne dir bitte an, in Zukunft gleich zu beschreiben, was du erreichen willst. Aus irgendwelchem vermurkstem Newbie-Code zu erraten, was eigentlich gemacht werden soll, ist immer mehr als mühsam.
    I don't believe in rebirth. Actually, I never did in my whole lives.

    Kommentar


    • #3
      Die Count-Werte sind einer Gruppen-ID zugeordnet.

      Die 1 würde unter sich somit 50, 75 und 120 vereinen (insgesamt also 245), entsprechenöd wurde es nämlich in die Table eingetragen. So verhält es sich auch mit Grp_id 2 (140) und 3 (190).

      Das X, wie es im Code definiert wird, steht für 100. X soll von den Summen(!) der Grp_ids jeweils runterrechnen, bis X 0 ist. Das wäre am Beispiel von Grp_id 1 und Count also wie folgt, dass X kleiner sei als der letzte Eintrag unter Grp_1, der da wäre 120. Von 120 werden 100 abgezogen, übrig blieben 20 und dies wird geupdated. X wäre somit 0.

      Dann aber fährt X mit 100 von vorne los, diesmal aber bei Grp_id 2. Da 50 < 100, werden, nach Abzug von 50 aus X (X = 50) gelöscht. Die übrigen 50 werden dann gerechnet, bis X = 0 ist. 90 > X, weswegen 90 - 50 = 40, folgt ein Update und X = 0.

      Danach fährt das Script fort bei 3, wo beide, obrige Beispiele, wieder Anwendung finden.

      Das Problem ist also, dass der jetzige Code zwar bis X = 0 rechnet/arbeitet, jedoch nicht nach den Gruppen unter Grp_id unterscheidet.

      Kommentar


      • #4
        Hallo,

        Ich seh zwar immer noch nicht, wofür das gut sein soll und dein Erklärstil ist auch nicht wirklich tauglich für die Sendung mit der Maus, aber ich vermute, du musst einen Gruppenwechsel machen. Wie das geht, steht in meinem Blog.

        Gruß,

        Amica
        [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
        Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
        Super, danke!
        [/COLOR]

        Kommentar


        • #5
          Amica, ich gebe dir recht, dass ich mich schwer tue, das gut zu beschreiben, wo man sich alles im Kopf ausformuliert hat.
          Was mir aufgefallen ist, woran es scheitern mag, ist zu Beginn das Heraussuchen des letzten Tabelleneintrages.

          Wie gesagt, die Tabelle sieht zu Beginn so aus:

          ID_s | Grp_id | Count
          1 - 1 - 50
          2 - 1 - 75
          3 - 1 - 120
          4 - 2 - 90
          5 - 2 - 50
          6 - 3 - 80
          7 - 3 - 90
          8 - 3 - 20

          Der Code soll - im ersten Schritt - per Limit eigentlich die letzten Einträge einer Grp_id heraussuchen. Das wären jene, die dick markiert sind. Aber durch Limit wird ja "nur" der letzte Eintrag, also 8 - 3 - 20 herangezogen.

          Also sollte dieser Teil des Codes
          PHP-Code:
          $last "SELECT count, grp_id, id_s FROM testnull GROUP BY grp_id DESC LIMIT 1";

                   
          $result2 mysql_query($last) or die(mysql_error());
                   WHILE(
          $row2 mysql_fetch_array($result2))

                   {
                   
          $count $row2['count'];
                   
          $id_s $row2['id_s'];
                   
          $grp $row2['grp_id'];
                   } 
          geändert werden. Aber was wäre das? Oder gibt es da einen Trick?

          Kommentar


          • #6
            Mal wieder ein Fall für den „negativen Left Join“:

            Code:
            SELECT count, grp_id, id_s
            FROM testnull t1
            LEFT JOIN testnull t2
                ON t2.grp_id = t1.grp_id AND t2.count > t1.count
            WHERE t2.grp_id IS NULL
            Nicht getestet, bitte selbst probieren.

            Beispiele und Hintergrundinfos gibt's über die Forensuche zu o. g. Stichwort.
            [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
            Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
            Super, danke!
            [/COLOR]

            Kommentar


            • #7
              Das Problem ist im ersten Schritt (zu 90%) gelöst. Eigentlich war es recht einfach, aber manchmal sieht man den Wald vor lauter Bäumen nicht.

              PHP-Code:
              SELECT count_sMAX(datum_s), grp_idid_s FROM testnull GROUP BY grp_id ORDER BY id_s 
              Zwar stimmen die Aufzählungen noch nicht - neuestes Datum zu älteren Einträgen -, aber das wäre auch noch zu meistern.
              Werde mich hier dazu noch zu Worte melden.

              Kommentar


              • #8
                Zitat von krampi Beitrag anzeigen
                Zwar stimmen die Aufzählungen noch nicht - neuestes Datum zu älteren Einträgen
                Eben und das kannst du nur mit Unterabfragen (unbedingt unkorreliert) oder dem besagten Join (empfohlen) erreichen. Funktioniert mein Code nicht?
                [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                Super, danke!
                [/COLOR]

                Kommentar


                • #9
                  Deinen Code habe ich mir angesehen und über PHPmyAdmin auch eingesetzt, wobei ich den Fehler bekam, das count (oder inzwischen count_s) Ambigous sei (deswegen nannte ich es auch in count_s) um. Beim recherchieren traf ich auf die von mir genannte Lösung und hatte deinen Vorschlag nicht weiter verfolgt.

                  Da ich nun aber zu deiner Lösung komme, würde ich eine Verständnisfrage stellen wollen: Letzter Punkt, WHERE t2.grp_id IS NULL, wieso hast du das eingesetzt? Was bewirkt es?

                  Kommentar


                  • #10
                    Zitat von krampi Beitrag anzeigen
                    wobei ich den Fehler bekam, das count (oder inzwischen count_s) Ambigous sei
                    Hast Recht, die Spalten müssen mit dem vollen Namen angesprochen werden und es muss natürlich so heißen:
                    Code:
                    SELECT t1.count, t1.grp_id, t1.id_s
                    FROM testnull t1
                    LEFT JOIN testnull t2
                        ON t2.grp_id = t1.grp_id AND t2.count > t1.count
                    WHERE t2.grp_id IS NULL
                    Zitat von krampi Beitrag anzeigen
                    Letzter Punkt, WHERE t2.grp_id IS NULL, wieso hast du das eingesetzt? Was bewirkt es?
                    Das ist der eigentliche Trick beim negativen Left Join. Nimm's mal weg, dann siehst du es vielleicht schon.
                    [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                    Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                    Super, danke!
                    [/COLOR]

                    Kommentar


                    • #11
                      Hey, das hat doch super geklappt. Dafür schon meinen Dank. Dass ich auf die Lösung zu ambigious gekommen bin, hätte ich noch hinzufügen können/sollen. Aber immerhin: Verstanden.

                      Jetzt kommt - leider - ein darauffolgendes Problem. Dieses tritt aber nicht nur beim Join auf, sondern auch bei dem vorhergegangenen, von mir eingestellten Code:

                      Die Resultate sollen per While-Schleife und darin enthaltener If-Anweisung sozusagen bearbeitet werden. Beim ersten Code, wo es aber auch nur eine einzige grp_id gab, funktionierte dies. Aber sowohl mit meinem falschen als auch mit deinem Code werden die Ergebnisse aus der Abfrage nicht bearbeitet. Ich stelle jetzt erstmal den Code rein und dann folgen von mir Erläuterungen ihrer Funktion - in der Hoffnung, der Sendung mit der Maus näher zu kommen.

                      PHP-Code:
                      $buy 100;

                      $last "SELECT t1.count_s, t1.grp_id, t1.id_s, t1.datum_s\n"
                            
                      "FROM testnull t1\n"
                            
                      "LEFT JOIN testnull t2\n"
                            
                      " ON t2.grp_id = t1.grp_id AND t2.datum_s > t1.datum_s\n"
                            
                      "WHERE t2.grp_id IS NULL";

                               
                      $result2 mysql_query($last) or die(mysql_error());
                               WHILE(
                      $row2 mysql_fetch_array($result2))

                               {
                               
                      $count $row2['count_s'];
                               
                      $id_s $row2['id_s'];
                               
                      $grp_id $row2['grp_id'];
                               }


                      WHILE (
                      $buy>0)
                               {
                               
                      IF (
                      $buy<$count)
                               {
                                
                      $count $count $buy;
                                echo 
                      "$buy ";
                                
                      $exdel3 
                      "UPDATE testnull SET count_s = $count WHERE grp_id = $grp_id DESC LIMIT 1";
                                
                      $delorder2 mysql_query($exdel3);
                                
                      $buy 0;
                               }

                               ELSE
                               
                      {
                               
                      $buy $buy-$count;
                               echo 
                      "$buy ";
                               
                      $delete 
                      "DELETE FROM testnull WHERE grp_id = $grp_id DESC LIMIT 1";
                               
                      $loesch mysql_query($delete);
                               }

                               } 
                      Zur Funktion. Es werden die Daten aus einer Tabelle herausgeholt, die von den Daten so ausschaut:

                      Die Tabelle sähe somit so aus:
                      ID_s | Grp_id | Count
                      1 - 1 - 50
                      2 - 1 - 75
                      3 - 1 - 120
                      4 - 2 - 90
                      5 - 2 - 50
                      6 - 3 - 80
                      7 - 3 - 90
                      8 - 3 - 20

                      Folglich liegt die Summe in Gruppe 1 bei 245, bei Gruppe 2 140 und in Gruppe 3 bei 190, wie im ersten Post beschrieben.

                      Ablaufen soll es wie folgt:
                      SELECT fragt die Tabelle nach den letzten Eintrag einer Grp_id ab, die wären

                      ID_s | Grp_id | Count
                      3 - 1 - 120
                      5 - 2 - 50
                      8 - 3 - 20

                      Wenn der jeweilige letzte Eintrag größer ist als Buy mit 100, wird Buy von Count abgezogen, ansonsten, wenn Count = buy oder Count < buy wird Count gelöscht, nachdem Buy aktualisiert wurde, also von Buy der jeweilige Count-Wert subtrahiert wird. Das würde wie folgt aussehen.

                      ID_s | Grp_id | Count | Buy
                      3 / 1 / 120 > 100 = 20 / 0 -> Eintrag wird aktualisiert, da > 0
                      5 / 2 / 50 < 100 = 0 / 50 -> Eintrag wird gelöscht, da 0
                      8 / 3 / 20 < 100 = 0 / 80 -> Eintrag wird gelöscht, da 0

                      Damit wäre 120 bearbeitet und Buy in diesem Teil der Tabelle auf 0.
                      Jedoch wären noch die zwei anderen Einträge zu bearbeiten, wo der neueste "letzte" Eintrag zugezogen würde.

                      ID_s | Grp_id | Count | Buy

                      4 / 2 / 90 > 50 = 40 / 0 -> Eintrag wird aktualisiert, da > 0
                      7 / 3 / 90 > 80 = 10 / 0 -> Eintrag wird aktualisiert, da > 0

                      Das Problem ist halt, dass es nicht zu einer Bearbeitung kommt. Ich könnte mir denken, dass es daran liegt, es im Grunde nur ein $buy gibt, das sich die Datenreihen teilen müssten.
                      Doch ansonsten ist es doch eigentlich das selbe, würd ich meinen?

                      Kommentar


                      • #12
                        Zitat von krampi Beitrag anzeigen
                        ...
                        ID_s | Grp_id | Count | Buy

                        4 / 2 / 90 > 50 = 40 / 0 -> Eintrag wird aktualisiert, da > 0
                        7 / 3 / 90 > 80 = 10 / 0 -> Eintrag wird aktualisiert, da > 0

                        Das Problem ist halt, dass es nicht zu einer Bearbeitung kommt. Ich könnte mir denken, dass es daran liegt, es im Grunde nur ein $buy gibt, das sich die Datenreihen teilen müssten.
                        Doch ansonsten ist es doch eigentlich das selbe, würd ich meinen?
                        wäre es nicht viel einfacher, wenn du mittels sum(count) erstmal die einzelnen Counts der jeweiligen Gruppen aufsummierst und davon dann dein Buy abziehst ?

                        du schreibst ja selbst weiter oben, dass Gruppe 1 nen Gesamt-Count von 245 hat .. da wäre es doch in meinen Augen viel sinnvoller, wenn in der Ergebnis-Tabelle nur noch steht
                        Code:
                        id | grp_id | count
                        1  |  1     |  145
                        2  |  2     |   40   
                        3  |  3     |   90
                        mithin ist immer noch sehr schwer ersichtlich, welchem Zweck die Berechnung dienen soll, die du da machst ...
                        Zuletzt geändert von eagle275; 24.06.2010, 10:21.
                        [font=Verdana]
                        Wer LESEN kann, ist klar im Vorteil!
                        [/font]

                        Kommentar


                        • #13
                          Zitat von eagle275 Beitrag anzeigen
                          wäre es nicht viel einfacher, wenn du mittels sum(count) erstmal die einzelnen Counts der jeweiligen Gruppen aufsummierst und davon dann dein Buy abziehst ?
                          Einfacher schon, nur würde er dann etwas völlig anderes ausrechnen als er vor hat. Dass der Sinn uns nicht eingeweihten weitgehend verborgen bleibt, darin muss ich dir allerdings zustimmen.
                          [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                          Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                          Super, danke!
                          [/COLOR]

                          Kommentar


                          • #14
                            ok, Amica.. wenn das so ist ..
                            PHP-Code:
                            $buy=100;
                            $result=mysql_query("SELECT * FROM Muelltabelle");
                            // von hinten nach vorne durch die Tabelle, um immer den letzten Eintrag einer Gruppe zuerst zu prüfen
                            for($i=count($result)-1;$i>=0;$i--) {
                               if (
                            $result[$i]['count']>=$buy) { // COUNT>BUY
                                  
                            $nw=mysql_query"UPDATE Muelltabelle SET count='".$result[$i]['count']-$buy."' WHERE id='".$result[$i]['id']."' " );
                                  
                            $cc=$result[$i]['grp_id']; // UPDATEN und GRUPPE zwischenspeichern
                                  
                            while ($result[$i]['grp_id']==$cc) {
                                     
                            $i--;  // vorrücken zum ersten Eintrag dieser Gruppe
                                  

                                  
                            $buy=100//buy wieder auf 100 setzen
                                  
                            $i++; //(korrektur)
                               
                            }
                               else { 
                            // count < buy -> löschen
                                  
                            $nw=mysql_query"DELETE FROM Muelltabelle WHERE id='".$result[$i]['id']."' " );
                                  
                            $buy-=$result[$i]['count']; // buy um gelöschtes count reduzieren
                               
                            }

                            wenn es halt nicht separat geht, dann lesen wir halt deine ganze Tabelle ein und bearbeiten sie mit geschachtelter Schleife - nicht elegant - aber es tut was es soll (wenn ich mich nicht irre ihihi ^^

                            einziger Punkt der mir beim 3ten Korrekturlesen auffällt - da müsste der Fall behandelt werden, wenn eine Gruppe nicht ausreicht, um dein anfängliches Buy von 100 zu erfüllen ...
                            Zuletzt geändert von eagle275; 24.06.2010, 11:11.
                            [font=Verdana]
                            Wer LESEN kann, ist klar im Vorteil!
                            [/font]

                            Kommentar


                            • #15
                              Fleißmeise!

                              Ist aber falsch, weil der $buy-Wert pro Gruppe weiterverwendet werden soll. Da würde sich ein Array anbieten. Aber der Fragesteller wird das mit deiner Codevorlage sicher selbst hinbekommen.
                              [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                              Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                              Super, danke!
                              [/COLOR]

                              Kommentar

                              Lädt...
                              X