Natürliche Sortierung

Natürliche Sortierung

Natürliche Sortierung bedeutet beispielsweise die Ausgabe folgender Daten 1A, 10C, 10A, 2A, 3B in der folgenden Reihenfolge. Die führenden Ziffern werden dabei als Zahlen interpretiert: 1A, 2A, 3B, 10A, 10C.

Mit der üblichen ORDER BY-Klausel ist das Ergebnis nicht zu erzielen. Das folgende Beispiel zeigt das Standardverhalten.

Die Ausgabe erfolgt in der Sortierung: 10A, 10C, 1A, 2A, 3B – sie ist offensichtlich alphabetisch.

Es gibt nun verschiedene Herangehensweisen, das Problem zu lösen, die gewünschte Sortierung zu erhalten.

Natürliche Sortierung durch Zerlegung

Die einfachste und m.E. offensichtlichste Möglichkeit besteht darin, das Datenfeld item in zwei Teile zu zerlegen.

Bei der Ausgabe wird dann erst numerisch nach dem Datenfeld itemno und danach alphabetisch nach dem Feld itemstr sortiert. Damit die Ausgabe den Erwartungen entspricht werden die beiden Felder mittels CONCAT zusammengefügt.

Diese Form der Zerlegung ist immer möglich.

Natürliche Sortierung dynamisch bestimmen

Trennzeichen

Manchmal lässt es die Datenbeschaffenheit zu, ein stets eindeutig vorhandenes Trennzeichen zu nutzen. Betrachten wir eine leichte Modifikation der oben vorgestellten Daten.

Für eine natürliche Sortierung müssen wir ein Item für die Sortierung in den linken und rechten Teil vom Bindestrich zerlegen und die beiden Teile separat sortieren. Mit den integrierten Funktionen POSITION und SUBSTRING, die wohl vielen zuerst einfallen, kann das leicht bewirkt werden. Der resultierende Code wäre aber etwas umständlich. Man würde sich wohl selbst entsprechende Funktionen schreiben, die unter Ausnutzung dieser Funktionen den linken und rechten Teil eines Items liefern.

Vielleicht weniger bekannt, aber für unsere Zwecke sehr viel einfacher zu nutzen, ist die integrierte Funktion SUBSTRING_INDEX. Sie liefert die Teilzeichenkette vor dem n-ten Auftreten des angegebenen Trennzeichens. In unserem Fall taucht das Trennzeichen nur einmal auf. Wir benötigen den linken und den rechten Teil. Das ist einfach.

Positive Zähler beginnen links, negative Zähler rechts. Daher erhalten wir mit -1 den rechts stehenden Teil eines Items. Das Ganze funktioniert auch bei komplexeren Strukturen.

Trick: Längenfunktion

Je nach Datenlage können wir uns aber eventuell auch eines weniger offensichtlichen Tricks bedienen. Dazu müssen die Daten allerdings entsprechend beschaffen sein. Nehmen wir an, es gebe immer eine Kennung, die aus einem einzelnen Buchstaben bestehe, der zudem immer gleich ist. Dem folgt dann eine Ziffernfolge, die die eigentliche Reihenfolge bei der Sortierung bestimmen soll.

Wie gehabt, funktioniert ein einfaches ORDER BY nicht entsprechend dem, was wir uns wünschen. Wir können in diesem Fall aber die Länge der Zeichenketten ausnutzen. Längere Zeichenketten sind größer als kürzere. Innerhalb gleicher Längen funktioniert die alphabetische Sortierung. Das liegt daran, weil die Ziffern in allen Zeichensätzen mit 0 bis 9 durchnummeriert sind.

Das funktioniert nicht mehr, wenn die Datensätze mit unterschiedlichen Buchstaben beginnen!

Reguläre Ausdrücke

MySQL wäre nicht MySQL, gäbe es nicht auch für solche Problemstellungen eine einfache Lösung. Die betrachteten Beispieldaten seien die folgenden:

Wir habe verschiedene Buchstaben und verschiedene Anzahlen von Buchstaben, die dem numerischen Teil vorstehen. Mithilfe regulärer Ausdrücke ist es jedoch ein Leichtes, auch diese Daten einer natürlichen Sortierung zuzuführen. Wir müssen lediglich den alphanumerischen Teil vom numerischen Teil trennen. Da diese Teile jeweils unterschiedlich lang sein können, bieten sich reguläre Ausdrücke an, ein Item zu analysieren und für die Sortierung passend zu zerlegen. Selbstgeschriebene Funktionen sind natürlich auch möglich, m.E. aber viel zu umständlich und letztlich auch wohl langsamer.

Das Statement sieht komplizierter aus, als es ist. REGEXP_SUBSTR(item, '^[[:alpha:]]*') extrahiert alle führenden Zeichen, die keine Ziffern sind. Der zweite Teil des Sortierausdrucks extrahiert alle Ziffern am Ende der Zeichenkette und wandelt Sie in ganze Zahlen um – sie werden jetzt numerisch sortiert. Sehen Sie sich die Dokumentation zu regulären Ausdrücken an. Es gibt neben REGEXP_SUBSTR noch weitere Funktionen, die reguläre Ausdrücke unterstützen.

Fazit

Auch wenn MySQL die natürliche Sortierung nicht direkt unterstützt, ist es dennoch ein Leichtes, diese für gegebene Daten zu bewirken. Im günstigsten Fall haben wir Einfluss auf das Datenbankdesign, wie im ersten Fall gezeigt. Der Trick mit der Längenfunktion ist ein echter Sonderfall. Er zeigt aber sehr schön, wie mit ein wenig Fantasie ein Workaround gefunden werden kann.

Reguläre Ausdrücke bieten dagegen einen sehr allgemeinen Ansatz, das Problem einer natürlichen Sortierung lösen zu können. Wer mit ihnen nicht vertraut ist, wird dann eventuell ein wenig herumexperimentieren müssen.

Karsten Brodmann

Karsten Brodmann hat an der Universität Osnabrück BWL/Wirtschaftsinformatik studiert. Er hat viele Jahre in der IT gearbeitet und dort Web- und Datenbankanwendungen entwickelt. Seit Gründung der Punkt-Akademie veröffentlicht Karsten Brodmann auch Schulungsvideos zur Datenbankentwicklung, Unix und Programmierung bei Udemy. In seiner Freizeit fotografiert Karsten Brodmann gerne. Seit vielen Jahren fotografiert er analog und digital. Dabei behält er jeweils den gesamten Workflow in der eigenen Hand, von der Aufnahme über die Dunkelkammer oder auch den Scanner sowie die Bildbearbeitung und den Ausdruck am PC.

Weitere Beiträge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.