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



## ManicMarble (24. März 2004)

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:


```
$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


----------



## XChris (25. März 2004)

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


----------



## aquasonic (25. März 2004)

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...


----------



## ManicMarble (25. März 2004)

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


----------



## Thomas Pinske (25. März 2004)

Hallo Martin,

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


```
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


----------



## vop (25. März 2004)

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


----------



## melmager (25. März 2004)

> 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


----------



## ManicMarble (25. März 2004)

@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

```
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:

```
... 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


----------



## Christian Proske (2. Mai 2011)

> SET @c := 0;
> UPDATE test SET platz = ( SELECT @c := @c + 1 ) ORDER BY id ASC;



gefunden auf: http://www.cix-blog.de/thm/MySQL-Update-soll-Spalte-neu-nummerieren


----------

