2009-02-26 5 views
1

Ich möchte eine zusätzliche Spalte in einer Tabelle als 'Sortierwert' speichern, was eine numerische Darstellung der Titelspalte ist , so dass die Reihenfolge solcher Werte die natürliche alphabetische Sortierreihenfolge der Zeichenfolge darstellt. Das heißt, dass ich nach dem Sortierwert sortierte Zeilen abrufen kann und sie in natürlicher Sortierreihenfolge vorliegen. Wenn ich eine neue Zeile einfüge, kann ich den numerischen Wert generieren und wissen, dass der Wert relativ zu anderen die Position der Zeichenfolge darstellt in einer alphabetischen Suche, genau auf die ersten X Buchstaben oder so.Erhalten numerischer/normalisierter Darstellung von Strings zur Unterstützung der 'natürlichen Sortierung' von Titeln in DB

Ein paar Gründe dafür: Erstens möchte ich eine natürlichere Bestellung als eine einfache Bestellung von einem DB-Server angeboten, wo Dinge wie "The" und "A" und Interpunktion am Anfang ignoriert werden, und Zahlen werden "natürlich" behandelt.

Zweitens ist dies für einen Index mit einer Vielzahl von Permutationen - es spart Platz und vielleicht Zeit beim Durchlaufen eines Index mit vielen Zeilen.

Was ich danach bin, ist der Algorithmus, um die Zeichenkette auf diesen numerischen Wert zu übersetzen, oder einfach, ich nehme an, ein normalisierter Zeichenkettenwert.

Ich benutze PHP und MySQL.

Ich fürchte, dass "alles aus der DB ziehen und in PHP mit natcasesort() sortieren" ist keine Lösung für diese besondere Situation, wie ich Zeilen (mit Reihenfolge von und Gruppe von) in abrufen möchte sortierte Reihenfolge, bevor sie zu einer Join- oder Limit-Klausel gelangen. Vielen Dank.

Edit:

Danke für Antworten so weit. Mir ist gerade eingefallen, dass die Tatsache, dass meine Anwendung UTF-8 verwendet, ziemlich relevant ist. Ich denke, dass es praktisch ist, den Anfangsteil einer Zeichenkette in gepackter/numerischer Form darzustellen, vielleicht nur eine Art normalisierter Form (alles fallgefüllt, Zahlen null gepolstert und so viele Zeichen wie möglich) normalisiert auf ihre Wurzel dh ã zu a) wäre angemessen.

+0

Ich bin mir nicht sicher, ob ich vollständig verstehe - wenn Sie von einer Zeichenfolge in eine Zahl übersetzen, werden Sie einige der Charaktere loswerden? –

Antwort

0

Danke für die Antworten bisher. Ich wollte nur Leute mit der Lösung aktualisieren, mit der ich gehe. Ich habe einen Ansatz gewählt, der sich von dem unterscheidet, was ich in meiner Frage ins Auge gefasst habe.

Zur Erinnerung, ich wollte eine Darstellung von Strings speichern, so dass, wenn in binärer Reihenfolge abgerufen, alles, was ich für "8 Mile" gespeichert habe, vor allem, was ich für "101 Dalmations" gespeichert habe, sortiert wird.

Für jede Zahl in der Zeichenfolge, die im Wesentlichen eine Folge von Ziffern ist, füge ich eine Ziffer vor sie, die beschreibt, wie viele Ziffern die Zahl ist.

So wird "8" zu "18" und "101" wird zu "3101". Es fügt der Zahl einige Redundanz hinzu, indem Sie mehr Ziffern verwenden, als Sie benötigen, und einige Werte werden nicht existieren, aber sie haben jetzt die Eigenschaft, dass eine binäre Sortierung die Zahlen in numerischer Reihenfolge sortiert. "101" hätte zuvor vor "8" sortiert, was unerwünscht war. Nach dem Hinzufügen dieser zusätzlichen Ziffer sortiert "18" vor "3101".

Hinweis: Wenn die Nummer 9 oder mehr Ziffern lang ist, füge ich zwei Ziffern zum Anfang hinzu: die Anzahl der Ziffern in der Zahl minus 9, dann eine 9, dann die Zahl. Dies ermöglicht Nummern bis zu 18 Ziffern: gut genug für mich.

Ich normalisiere die Zeichenfolge auch auf andere Weise - alles in Kleinbuchstaben, Unicode-Zeichen werden in die nächste Ascii-Entsprechung übersetzt, und 'a', 'an' und 'the' werden entfernt, wenn sie sind das erste Wort.

Ich habe aufgegeben, die Zeichenfolge in einen großen numerischen Wert zu machen; Es ist immer noch eine Zeichenfolge, es ist nur, dass es nicht für Menschen zum Lesen gedacht ist.

+0

Ich habe diese Lösung implementiert, also hoffe ich, dass es Ihnen nichts ausmacht, aber ich werde meine eigene Antwort hier akzeptieren. – thomasrutter

1

Der Teil "genau auf den ersten X Buchstaben oder so" ist entscheidend, da eine völlig genaue Zuordnung von Zahlen unmöglich ist. Um dies zu sehen, nehmen Sie zur Konkretheit an, dass Ihre title Spalte varchar(50) ist und Sie eine 32-Bit integersort_order Spalte verwenden möchten. Dann könntest du (255^51 - 1) verschiedene Titel speichern, von denen jeder einen anderen sort_order Wert benötigt - aber es gibt nur 2^32 verschiedene sort_order Werte, um die es gehen kann. Selbst wenn Sie sagen würden, dass Sie niemals mehr als 2^32 Zeilen hinzufügen würden, müssten Sie im Voraus wissen, welche Titel sie haben würden, um ein Schema zu erstellen, das bei jedem Einfügen einer Zeile nicht alle sort_order Werte neu zuweisen muss.

Obwohl eine "theoretisch perfekte" Lösung unmöglich ist, ist es immer noch möglich, ein praktisches "ungefähres" System zu finden, das mit perfekter Genauigkeit für bis zu viele Millionen Zeilen arbeiten sollte. Am einfachsten wäre es, einen Fließkommatyp zu verwenden. Listen Sie zuerst die Zeilen in sortierter Reihenfolge auf und weisen Sie der ersten Zeile einen sort_order Wert von 1,0 zu, die zweite einen Wert von 2,0 und so weiter. Wenn eine Zeile eingefügt wird, stellen Sie dann sort_order auf den Mittelpunkt (dh den Durchschnitt) der Zeilen auf jeder Seite in sortierter Reihenfolge ein. Wenn die neu hinzugefügte Zeile vor (oder nach) allen vorhandenen Zeilen steht, setzen Sie sie einfach auf 1 weniger als (oder mehr als) den vorherigen minimalen (oder maximalen) Wert sort_order.

Es ist eine gute Idee, Nummern von Grund auf neu zuzuweisen (wie im anfänglichen Erstellungsschritt), um die Werte regelmäßig oder nach einer großen Anzahl von Aktualisierungen zu "glätten".Besonders wenn der Tisch klein anfängt und dann groß wird, kann es sein, dass sich an den Enden etwas "Bündeln" von Zahlen findet.

+0

Ich dachte eher an die Linien von SoundEx, das eine 4-stellige Darstellung des phoenetischen Lautes eines Wortes ist, wo ähnlich klingende Wörter nahe beieinander liegen. Die obige Lösung würde eine Suche nach ähnlichen Werten für jede Einfügung erfordern und es notwendig machen, ganze Zeichenfolgen mit jeder Zeile zu speichern. – thomasrutter

+0

Es tut mir leid, als ob ich den Teil Ihrer Frage ignoriert habe, in dem Sie davon gesprochen haben, "das" und "a" usw. ausziehen zu wollen und völlig falsch interpretiert zu haben, was Sie wollten! –

Verwandte Themen