MySQL: Feld über mehrere Sätze neu durchnummerieren?

ManicMarble

Erfahrenes Mitglied
Hallo,
ich bin ganz neu hier und möchte mal fragen, ob jemand eine bessere Lösung für folgendes Problem weiß:

Ich möchte in MySQL ein Feld über eine Reihe von Datensätzen neu von 1 bis x durchnummerieren. Es handelt sich um ein Sortierfeld, mit dessen Hilfe der Anwender die Position eines DS in einer Anzeigeliste selbst bestimmen kann.

Meine Lösung sieht momentan so aus:
Ich setze voraus, dass das Feld sortorder über alle betroffenen DS nur ganze Zahlen in aufsteigender Reihenfolge enthält. Der User bestimmt nun beispielsweise, dass er Zeile 10 hinter Zeile 5 verschieben möchte. Das Programm schreibt bei Satz 10 den Wert 5.5 in sortorder. Damit nun wieder in allen Sätzen ganze Zahlen stehen, werden per Script alle Sätze selektiert (sortiert nach sortorder) und in einer Schleife wird ein inkrementierender Wert beginnend bei 1 in sortorder geschrieben. In PHP sieht das in etwa so aus:

PHP:
$sql = "SELECT id,sortorder FROM table WHERE (userid = 'x') ORDER BY sortorder";
$rst = mysql_query($sql, $con)
$i = 1;
while ($row = mysql_fetch_assoc($rst)) {
	mysql_query("UPDATE table SET sortorder = '".$i."' WHERE id = '".$row["id"]."' LIMIT 1", $con)
	$i++;
}
mysql_free_result($rst);

Frage:
Gibt es für diese Neu-Nummerierung auch eine schnelle, reine SQL-Lösung? Habe bereits mit Variablen experimentiert, was ich mir etwa so vorgestellt habe:

SET @i=0;
UPDATE table SET sortorder = (@i := @i + 1) ORDER BY sortorder


Aber das hat nicht funktioniert. Kann es sein, dass meine MySQL-Version (MySQL-Max 3.23...) das ORDER BY für UPDATE noch nicht unterstützt (die MySQL-Doku http://www.mysql.com/doc/de/UPDATE.html sagt nichts dergleichen). Ohne ORDER BY funktioniert's theoretisch, allerdings werden die Sätze dann in der Reihenfolge ihres Einfügens durchnummeriert.

Wäre über jegliche Anregung höchst erfreut - vielleicht habe ich mich auch völlig verrannt und es gibt eine ganz simple Lösung...

Viele Grüße aus dem Allgäu
 
Ich würd es so versuchen:

Neue Tabelle Anlegen mit einem Autoindex. Dann die bestehenden Werte aus der einen tabelle mittels einem INSERT - SELECT kopieren und dabei mit ORDER BY die richtige Reihnfolge beachten.
Danach wird ich die alte Tabelle Löschen und die neue Umbenennen. (DROP und ALTER)

Chris
 
Das ist aber noch viel langsamer als seine Lösung. Ich denke schon das es eine solches Statement gibt, dafür ist aber mein SQL wirklich zu schlecht...:(
 
Hallo Chris,
danke für die Antwort. Leider ist das nicht genau das was ich will. Habe mich wahrscheinlich nicht ganz klar ausgedrückt - ist aber auch schwer zu beschreiben, das Problem.

Das Neu-Nummerieren betrifft nicht die ganze Tabelle, sondern immer nur die Datensätze eines bestimmten Benutzers (WHERE userid = 'x'). Es geht auch nicht um die auto_incrementierte Datensatz-ID (Primary Key), ein solches Feld hat die Tabelle natürlich auch, die Sortierung hat mit der ID aber nichts zu tun. Das Neunummerieren ist auch nicht eine einmalige Sache um die Tabelle aufzuräumen, vielmehr würde diese Aktion immer dann gebraucht, wenn ein Anwender einen seiner Listeneinträge hoch oder runteschieben will. Ein Neu-Erstellen der ganzen Tabelle wäre in dieser Situation meiner Ansicht nach etwas zu brutal.

Trotzdem Danke,
Martin
 
Hallo Martin,

ich bin mir nicht sicher ob MySQL das versteht, aber einen Versuch wäre es wert:

Code:
UPDATE table SET sortorder=sortorder+1 WHERE sortorder>="NeuePos" AND sortorder<"AltePos"

"NeuePos" und "AltePos" muss mit der neuen und alten Position des zu verschiebenden DS ersetzt werden.

Grüße Thomas
 
Hi Resalb,

wäre es vielleicht eine Idee, eine weitere Spalte für die neue Position zu verwenden, die dann später für die Sortierreihenfolge herangezogen wird?

UPDATE ... set SortOrder = NeueSortOder?

BTW:

Von einem Update .. ORDER BY habe ich generell noch nie etrwas gehört.
Wozu soll das gut sein? Die Datensätze werden doch nicht sortiert gelagert sondern willkürlich. Eine Sortierung wird ggf. durch einen Index unterstützt, nicht jedoch durch eine Vorgabe, in welcher Reihenfolge einzelne Datensätze aktualisiert werden.

Oder habe ich Dich total missverstanden?
vop
 
Der User bestimmt nun beispielsweise, dass er Zeile 10 hinter Zeile 5 verschieben möchte. Das Programm schreibt bei Satz 10 den Wert 5.5 in sortorder. Damit nun wieder in allen Sätzen ganze Zahlen stehen, werden per Script alle Sätze selektiert

ok deine 5 haste sicher noch als Variable :)

update table set sortorder = floor(sortorder)+1 where sortorder > '$var' and userid = '$userid'

und schon sind alle einträge um eins hochgezählt
 
@Thomas,

Danke für den Tipp, das sieht erst mal vielversprechend aus. Mals seh'n ob ich das richtig verstanden habe:
In dem Beispiel, wo Zeile 10 hinter Zeile 5 verschoben werden soll, würde zunächst in Satz 10 bei sortorder 5.5 reingeschrieben. Dann würde
Code:
UPDATE table SET sortorder = FLOOR(sortorder+1) WHERE sortorder >= '5.5' AND sortorder < '10' AND userid = 'x'
nur die Datensätze 5.5 bis 9 neu nummerieren, alle anderen sind ja nicht betroffen, das FLOOR is wohl zus. nötig, damit aus 5.5 nicht 6.5 sondern 6 wird.
Wie ist das dann aber in umgekehrter Richtung? Schiebe 5 hinter 10, schreibe also 10.5 in sortorder von 5. In dem Fall müsste das also umgedreht werden:
Code:
... WHERE sortorder > 'altePos' AND sortorder < 'neuePos+1'
Das ist ja kein Problem, dann gibt's halt 2 unterschiedliche SQL-Statements.

Super, ich denke das ist es! Werde das gleich so machen. Vielen Dank.

@melmager:
Hab' Dein Posting grade erst gesehen. Das ist im Prinzip das was Thomas vorgeschlagen hat, nur "nach oben hin offen". Danke trotzdem.

@vop:
Das ORDER BY im Zusammenhang mit UPDATE kannte ich bisher auch nicht. Ich fand dann den Satz "Wenn die ORDER BY-Klausel angegeben ist, werden die Zeilen in der angegebenen Reihenfolge aktualisiert" in der MySQL-Doku unter http://www.mysql.com/doc/de/UPDATE.html und dachte, das könnte mir helfen. War aber ein Irrweg, wo die Lösung doch so einfach ist.

Grüße,
Martin
 

Neue Beiträge

Zurück