Wenn Sie eine Datenbank verwenden, müssen Sie häufig in der richtigen Reihenfolge auf Datensätze zugreifen. Wenn ich beispielsweise ein Blog habe, möchte ich meine Blog-Posts in beliebiger Reihenfolge neu anordnen können. Diese Einträge haben oft viele Beziehungen, daher scheint eine relationale Datenbank sinnvoll zu sein.
Die gebräuchliche Lösung, die ich gesehen habe, ist das Hinzufügen einer Ganzzahlspalte order
:
CREATE TABLE AS your_table (id, title, sort_order)
AS VALUES
(0, 'Lorem ipsum', 3),
(1, 'Dolor sit', 2),
(2, 'Amet, consect', 0),
(3, 'Elit fusce', 1);
Dann können wir die Zeilen sortieren order
, um sie in der richtigen Reihenfolge zu erhalten.
Dies scheint jedoch ungeschickt:
- Wenn ich Datensatz 0 an den Anfang verschieben möchte, muss ich jeden Datensatz neu anordnen
- Wenn ich einen neuen Datensatz in der Mitte einfügen möchte, muss ich jeden Datensatz danach neu anordnen
- Wenn ich einen Datensatz entfernen möchte, muss ich jeden Datensatz danach neu anordnen
Es ist leicht, sich Situationen wie die folgenden vorzustellen:
- Zwei Datensätze haben das gleiche
order
- Es gibt Lücken
order
zwischen den Datensätzen
Diese können aus einer Reihe von Gründen relativ leicht vorkommen.
Dies ist der Ansatz, den Anwendungen wie Joomla verfolgen:
Sie könnten argumentieren, dass die Benutzeroberfläche hier schlecht ist und dass Menschen, anstatt Zahlen direkt zu bearbeiten, Pfeile oder Drag-and-Drop verwenden sollten - und Sie hätten wahrscheinlich Recht. Aber hinter den Kulissen passiert das Gleiche.
Einige Leute haben vorgeschlagen, eine Dezimalzahl zum Speichern der Reihenfolge zu verwenden, sodass Sie "2.5" verwenden können, um einen Datensatz zwischen den Datensätzen in Reihenfolge 2 und 3 einzufügen seltsame Dezimalstellen (wo hören Sie auf? 2,75? 2,875? 2,8125?)
Gibt es eine bessere Möglichkeit, Bestellungen in einer Tabelle zu speichern?
quelle
orders
und dem ddl behoben .Antworten:
Nein, es gibt einen einfacheren Weg.
Das ist wahr, es sei denn, Sie verwenden einen Datentyp, der "zwischen" Werten unterstützt. Mit Float- und numerischen Typen können Sie einen Wert beispielsweise auf 2,5 aktualisieren. Aber auch varchar (n) funktioniert. (Denken Sie an 'a', 'b', 'c'; dann denken Sie an 'ba', 'bb', 'bc'.)
Nein, es gibt einen einfacheren Weg. Löschen Sie einfach die Zeile. Die verbleibenden Zeilen werden weiterhin korrekt sortiert.
Eine eindeutige Einschränkung kann dies verhindern.
Lücken haben keinen Einfluss darauf, wie ein DBMS Werte in einer Spalte sortiert.
Sie hören nicht auf, bis Sie müssen . Das DBMS hat kein Problem damit, Werte mit 2, 7 oder 15 Nachkommastellen zu sortieren.
Ich denke , Ihr wirkliches Problem ist , dass Sie mögen , dass sehen Werte in sortierter Reihenfolge als ganze Zahlen. Das kannst du machen.
quelle
with cte as (select *,row_number() over (order by sort_order desc) as row from test) update cte set sort_order=row;
Es ist sehr einfach. Sie müssen eine "Kardinalitätsloch" -Struktur haben:
Sie müssen 2 Spalten haben:
integer
bigint
( nichtdouble
)Einfügen / Aktualisieren
order = round(max_bigint / 2)
.order = round("order of first record" / 2)
order = round("max_bigint - order of last record" / 2)
4) Beim Einfügen in der Mitte setzen Sieorder = round("order of record before - order of record after" / 2)
Diese Methode hat eine sehr große Kardinalität. Wenn Sie einen Einschränkungsfehler haben oder denken, dass Sie eine kleine Kardinalität haben, können Sie die Ordnungsspalte neu erstellen (normalisieren).
In der maximalen Situation mit Normalisierung (mit dieser Struktur) können Sie "Kardinalitätsloch" in 32 Bit haben.
Denken Sie daran, keine Gleitkommatypen zu verwenden - die Reihenfolge muss genau sein!
quelle
Im Allgemeinen erfolgt die Bestellung anhand einiger Informationen in den Aufzeichnungen, dem Titel, der ID oder was auch immer für die jeweilige Situation geeignet ist.
Wenn Sie eine spezielle Reihenfolge benötigen, ist die Verwendung einer Ganzzahlspalte nicht so schlecht, wie es scheint. Um beispielsweise Platz für eine Schallplatte zu schaffen, die auf den 5. Platz geht, können Sie Folgendes tun:
update table_1 set place = place + 1 where place > 5
.Hoffentlich können Sie die Spalte als
unique
"atomar" deklarieren und haben möglicherweise eine Prozedur, um Umlagerungen "atomar" zu machen. Die Details hängen vom System ab, aber das ist die allgemeine Idee.quelle
Wen interessiert das? Diese Zahlen sind nur für den Computer bestimmt, daher spielt es keine Rolle, wie viele Nachkommastellen sie haben oder wie hässlich sie uns erscheinen.
Die Verwendung von Dezimalwerten bedeutet, dass Sie zum Verschieben von Element F zwischen den Elementen J und K nur die Auftragswerte für J und K auswählen und dann den Durchschnitt bilden und anschließend F aktualisieren müssen Deadlocks).
Wenn Sie in der Ausgabe eher Ganzzahlen als Brüche sehen möchten, berechnen Sie die Ganzzahlen entweder in der Clientanwendung oder verwenden Sie die Funktionen ROW_NUMBER () oder RANK () (sofern diese in Ihrem RDBMS enthalten sind).
quelle
In meinem eigenen Projekt habe ich vor, eine Lösung zu versuchen, die der Lösung mit der Dezimalzahl ähnelt, aber stattdessen Byte-Arrays verwendet:
Die Idee ist, dass Ihnen niemals die möglichen Zwischenwerte ausgehen, da Sie nur ein
b"\x00"
an die beteiligten Datensätze anhängen , wenn Sie mehr Werte benötigen. (int
ist in Python 3 unbegrenzt, andernfalls müssten Sie am Ende einen Teil der zu vergleichenden Bytes auswählen. Dabei wird davon ausgegangen, dass zwischen zwei benachbarten Werten die Differenzen gegen Ende gepackt werden.)Angenommen, Sie haben zwei Datensätze
b"\x00"
undb"\x01"
und möchten, dass ein Datensatz zwischen ihnen liegt. Zwischen0x00
und stehen keine Werte zur Verfügung.0x01
Fügen Sie alsob"\x00"
an beide Werte an, und Sie haben jetzt eine Reihe von Werten dazwischen, mit denen Sie neue Werte einfügen können.Die Datenbank kann es leicht sortieren, da alles in lexikografischer Reihenfolge endet. Wenn Sie einen Datensatz löschen, ist dieser noch in Ordnung. In meinem Projekt habe ich
b"\x00"
undb"\xff"
alsFIRST
undLAST
Datensätze erstellt, um diese als virtuelle "von" - und "bis" -Werte zum Voranstellen / Anhängen neuer Datensätze zu verwenden:quelle
Ich fand diese Antwort viel besser. Ich zitiere es ganz:
quelle