Stefan: Zeilen auf/ab bewegen

Servus!

Für eine Sortierungsmöglchkeit brauche ich einen Ansatz für folgendes Problem:
Gegeben sei eine Tabelle mit n Zeilen, jede Zeile hat einen Link für "auf" und "ab", außer die erste und letzte.
Generiert wird diese Reihenfolge aus einer MySQL-Datenbank, die eine eigene Spalte mit dem Rang hat (1..n). Nun möchte ich mit dem Link "auf" und "ab" den Rang verändern.
Folgendes ist mir dazu eingefallen:
-) auf: rang-1 auf die Seite legen, neuen Datensatz auf rang-1 legen, alten Datensatz auf rang legen. Also eigentlich nur vertauschen, ebenso abwärts.

Gibts da irgendwo fertige Codeschnippsel oder gar eine bessere Lösung?

Danke!

Grüße, Stefan

  1. Hallo Stefan,

    sollen die Datensätze zeilenweise bubbeln oder der angeklickte gleich ganz nach oben/unten springen?

    Gruß, Andreas

    --
    http://forum.andreas-lindig.de <img src="http://forum.andreas-lindig.de/bilder/logo.png" border="0" alt="">
    einfach mal testen und Meinung hinterlassen
    1. Servus!

      sollen die Datensätze zeilenweise bubbeln oder der angeklickte gleich ganz nach oben/unten springen?

      Jeweils eins rauf bzw. runter.

      Grüße, Stefan

      1. Hello,

        Servus!

        sollen die Datensätze zeilenweise bubbeln oder der angeklickte gleich ganz nach oben/unten springen?

        Jeweils eins rauf bzw. runter.

        Das ändert im Prinzip nicht viel am Aufwand. Allerdings kannst Du, wenn die Position keinen Unique Kombinationsschlüssel mit der ID hat, sie kurzfistig auch einfach doppelt belegen, also zwei Updates nacheinander durchführen.
        Hole beide Positionen, setze Position 1 = Postion 2 (die ist dann doppelt) und setze dann position 2 = Position 1

        Wenn das Script zwischendurch "abkackt" hast Du allerdings ein nicht reparierbares Durcheinander.
        Locken musst Du dann nur die beiden Datensätze für die dauer des Selects (mit Limit) und der beiden Updates.

        Harzliche Grüße aus http://www.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        1. Servus!

          Habs jetzt testhalber einmal so gelöst (Auszug):

          if($action == "up" && is_numeric($id)) {
          $rank = $db->getOne("select ranking from tbl_uebersicht where artikel_id="" . $id . """);

          $prev=$rank - 1;
          $next=$rank + 1;

          $query1 = "UPDATE tbl_uebersicht set ranking=0 where ranking=" . $prev;
          $res=$db->query($query1);
          echo $query1  . "<br>";

          $query2= "UPDATE tbl_uebersicht set ranking=" . $prev . " where ranking=" . $rank;
          $res=$db->query($query2);
          echo $query2 . "<br>";

          $query3 = "UPDATE tbl_uebersicht set ranking=" . $rank . " where ranking=0";
          $res=$db->query($query3);
          echo $query3 . "\n";

          }

          Danke!

          Grüße, Stefan

          1. Hello,

            diese Statements MÜSSEN durch ein Lock geklammert werden!

            $rank = $db->getOne("select ranking from tbl_uebersicht where artikel_id="" . $id . """);

            $query1 = "UPDATE tbl_uebersicht set ranking=0 where ranking=" . $prev;

            $query2= "UPDATE tbl_uebersicht set ranking=" . $prev . " where ranking=" . $rank;

            $query3 = "UPDATE tbl_uebersicht set ranking=" . $rank . " where ranking=0";

            Harzliche Grüße aus http://www.annerschbarrich.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau
  2. Hello,

    -) auf: rang-1 auf die Seite legen, neuen Datensatz auf rang-1 legen, alten Datensatz auf rang legen. Also eigentlich nur vertauschen, ebenso abwärts.

    Gibts da irgendwo fertige Codeschnippsel oder gar eine bessere Lösung?

    Die Datensatznummer (ID) hat nichts mit der Sortierung zu tun, sondern ausschließlich mit der Identifikation des Datensatzes. Su müsstest also eine weitere Spalte "psoition" (o.ä.) einführen. Das Problem wird sein, eine definierte Lücke zu schaffen.
    Aber da wird MySQL Dich unterstützen, da Selects generell als Snapshot gehalten werden und nicht als Dynaset.

    Du kannst also abfragen

    Update tabelle set position = position+1 where filterbedingung and position >= $minposition

    um eine Lücke zu schaffen und dann auf $minposition den Datensatz einzufügen und ihn anschließend an seiner alten Position zu löschen. Zu beachten ist, dass das Ding dann eine andere ID bekommt. Um daws zu vermeiden, kann man als erstes dem zu verschiebenden Datensatz die "MaxID" verpassen. dann kann man ihn unter seiner alten ID selbst bei einer Autoincrement-ID mit der neuen $position wieder einfügen.

    Man muss während des gesamten Vorganges die Tabelle Locken!

    Das Verfahren funktioniert ganz gut so. Ich habe bisher nur noch keine Möglichkeit für ein "Reindex" der $position gefunden. Die User-Variablen, die MySQL dafür eigentlich zur Verfügung stellen sollte, funktionieren leider nicht so, wie ich es bisher gedacht habe

    Harzliche Grüße aus http://www.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
  3. das problem ist, das 2 sätze geändert werden müssen.

    bei einem abbruch des scriptes führt dies natürlich zu inkonsistenz.

    daher muß man (my)sql dazu bewegen, beide sätze in einer query zu ändern.

    gegenben sei eine spalte 'Position', welche die stelle markiert,
    'P1' und 'P2' als die zu tauschenden positionen.

    um 2 sätze zu aktualisieren, muß das WHERE kriterium 2 sätze als resultset liefern:  WHERE Position IN (P1, P2)

    um jeweils den anderen inhalt in die db zu stellen, bietet sich an, die summe der beiden P's als modulo mit der momentanen P zu nehmen:

    UPDATE tabelle SET Position = MOD(P1+P2, Position)

    da P1 und P2 in php als variablen stehen, muß es dann heißen:

    UPDATE tabelle SET Position = MOD($P1+$P2, Position)
    WHERE Position IN ($P1, $P2)

    ob das konkurrierende update auch ohne commit möglich ist, müßte noch untersucht werden.

    1. tschuldigung, das passiert, wenn man gedanklich noch bei einer anderen aufgabe(seiner arbeit) ist.

      um jeweils den anderen inhalt in die db zu stellen, bietet sich an, die summe der beiden P's als modulo mit der momentanen P zu nehmen:

      falsch, nicht mod, sondern P von der summe weg!

      UPDATE tabelle SET Position = MOD(P1+P2, Position)

      UPDATE tabelle SET Position = (P1+P2) - Position)

      da P1 und P2 in php als variablen stehen, muß es dann heißen:

      UPDATE tabelle SET Position = MOD($P1+$P2, Position)
      WHERE Position IN ($P1, $P2)

      UPDATE tabelle SET Position = ($P1+$P2) - Position)
      WHERE Position IN ($P1, $P2)

    2. Hello,

      das problem ist, das 2 sätze geändert werden müssen.

      bei einem abbruch des scriptes führt dies natürlich zu inkonsistenz.

      Das führt auch bei konkurrierendem Zugriff eines anderen Scriptes zur Verwirrung ;-)

      MySQL unterstützt keine verbundenen Queries, denn MySQL ist kein echtes DBMS, sondern nur ein Rumpfsystem. Das konnte bTrieve schon vor 25 Jahren leisten.

      Harzliche Grüße aus http://www.annerschbarrich.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      Nur selber lernen macht schlau
      1. deshalb soll ja auch nur 1 query abgesetzt werden, welche beide sätze ändert.

    3. Hallo,

      Würdest du bitte aufhören das Eingabefeld für den Namen zu missbrauchen!

      Grüße
      Thomas

      1. hierzu gibts bereits einen thread.

        mir ist eigentlich völlig egal was da steht. wichtig ist nur die eindeutigkeit.

        wenns dir dann hilft, poste ich ab sofort mit 'fk'.