Varchar Sort mit Nummern

Hallo,

ich habe eine Spalte in einer Tabelle nach der sortiert werden soll. Sie ist vom Typ varchar und enthält Werte wie z.B. 1,2,3,12,13a,m16, usw. - also Zahlen und Buchstabenkombinationen.

Ist es möglich so zu sortieren, dass das Ergebnis danns o aussieht:
1
2
3
12
13a
m16

Im Moment würden 12 und 13a nach der 1 kommen. Mit CAST geht es ja leider nicht, da ein Fehler erzeugt wird sobal kein rein numerischer Wert übergeben wird.

Viele Grüße
Chris

Und wo sollen 13a und m16 einsortiert werden?

Ich glaube, dein Datenbankdesign ist völlig kaputt.
Mach das richtig, dann funktioniert das Sortieren auch ohne Probleme.

Punkt 1: ads hat Recht.

Punkt 2: PostgreSQL ist’s, wenn es dennoch geht:

test=*# select * from cevou ;
  a
-----
 m16
 13a
 2
 1
 3
 12
(6 Zeilen)

Zeit: 0,219 ms
test=*# select * from cevou order by regexp_replace(a,'[^0-9]','')::int;
  a
-----
 1
 2
 3
 12
 13a
 m16
(6 Zeilen)

Zeit: 0,296 ms

Fixe dein DB-Design!

Andreas

Danke für die Antworten,

ich bin ja immer bereit dazuzulernen. Was meint ihr mir “fixe dein Datenbankdesign”?
ISt es so “abnormal” eine varchar-Spalte so zu sortieren, dass die Zahlen in einer richtigen Reihenfolge stehen?

Ja. Entweder du möchtest nach Zahlen sortieren, dann nimm auch eine Spalte mit Zahlen da drin her. Oder du möchtest nach etwas anderem sortieren, dann dürfen das aber nicht nur Zahlen als Sortiervorgabe sein.

Dieses DB-Design ist fehlerhaft und lösst sich sicher besser implementieren. Außerdem ist das Sortieren hinterher sicherlich schneller als mit dem Workaround von akretschmer - der funktioniert zwar, ist aber nie im Leben schnell.

Das Problem ist, dass es in dem Programm keine festeVorgabe gibt für dieses Feld.
In der Regel sind es ja nur Zahlen - früher hatte ich es auch als Integer-Feld. Jetzt kann es aber halt durchaus vorkommen, dass anstatt nur einer Zahl 12a, 12b, 12c oder ähnliches feststeht.
Man könnte theoretisch ein Extrafeld für Prefix und Suffix - aber ist das die besser Lösung? Dann müsste ich wieder die komplette Tabelle neu aufbauen, weil ich ja keine Spalte an einer bestimmten Position einschieben kann.

Vielleicht sollte man sich Gedanken machen, ob der grundsätzliche Aufbau der Tabelle/Datenbank überhaupt Sinn macht.
Ich unterbreite da gern ein Angebot …

Es geht hier um ein Programm, das Sportwettkämpfe auswertet. Bei diesem Feld explizit geht es um die “Wettkampfnummern”.
Oft sind diese numerisch es kommt aber durchaus auch vor, dass halt Buchstaben mit zur Wettkampfnummer gehören.
Deshalb habe ich mich für ein varchar entschieden.
Du kannst mir gerne etwas vorschlagen ich bin über Hilfe immer sehr dankbar.

Was, ein Angebot für Support oder eine Lösung? :wink:

Versuch dich mal mit einer getrennten Spalte für die Sortierung, unabhängig von den Wettkampfnummern.
Alternativ schreib dir eine Sortierfunktion, die genau das abbildet, was du haben willst. Das wird zwar elendig langsam, aber funktioniert.

Stimmt, das wäre ein Ansatz. :slight_smile:

Bezüglich Support oder Lösung: Ich entwickle das Tool in meiner Freizeit und verdiene damit kein Geld, deshalb bin ich auch nicht bereit Geld in die ganze Sache reinzustecken. Wenn du mir so helfen willst meine Datenbankstruktur zu optimieren bin ich sofort dabei.

Dann zeig die Struktur doch erst mal.

So, auf zu einer Familienfeier …

Here you go…

Funktionale Indexe existieren - you know? :wink:

Andreas

Das ist dein nächster Denkfehler: die interne Struktur wie z.B. die Anordnung der Spalten hat rein gar nix mit der externen Darstellung zu tun. Du arbeitest ganz offensichtlich mit select * und insert into table values (…) in einem Produktivsystem - dies wird früher oder später knallen.

Andreas

Das ist nicht korrekt - ich habe in meinem Programm mit sehr vielen Abfragen genau null SELECT * und genau null insert into table values ().
Ich frage immer nur die Spalten ab di ich benötige (* wäre ja auch schwachsinnig bei mehreren JOINS hätten man ja dann zig Spalten)

So ganz der Noob bin ich auch nicht mehr :slight_smile:

Okay.

Andreas

Das ziehe ich mir jetzt nicht komplett alles rein, was mir aufgefallen ist:

  • exzessive verwendung von varchar(N). Nicht wirklich problematisch, aber text ist oft sinnvoller
  • tabelle tfx_teilnehmer, spalte int_geschlecht: das kann offensichtlich deutlich mehr werte aufnehmen, als sinnvoll sind …
  • es gibt noch ein paar mal smallint-felder, für dies möglicherweise auch zutrifft

Ich schreibe auch immer FK-Beziehungen gleich mit in die Tabellendefinition, da sieht man gleich, wie die aufgebaut sind. Vermutlich hat das ein Tool da bei generiert, oder?


Andreas

Ich habe das mal mit pgAdmin generiert.



pgAdmin “generiert” keinen Code, der macht im Prinzip bloß das, was du ihm anschaffst.
Was akretschmer angesprochen hat ist richtig: im ersten Augenblick kann man nicht sehen, ob eine deiner SERIAL-Spalten nun nur “NOT NULL” ist oder ob das wirklich ein PRIMARY KEY ist. Dafür müsste man für jede Tabelle noch mal nach unten scrollen und schauen, ob der PK irgendwo definiert wird.
Als Übersicht ist das unbrauchbar.

Die ungarische Notation in SQL zu benutzen kann später zu erheblichen Problemen führen, wenn du den Datentyp ändern musst. In deinem Beispiel musstest du ja schon mal einen INTEGER in einen VARCHAR ändern - deiner Logik zufolge müsstest du dafür auch den Spaltennamen ändern. Das wiederum zieht einen Haufen Arbeit und Anpassungen in der Applikation nach sich → das provoziert geradezu Fehler.

bol_maennlich und bol_weiblich als getrennte Felder zu führen ist äh krank. Ich sehe nicht, dass du irgendwo prüfst, ob nicht beide Spalten gleichzeitig gesetzt sein könnten. Aus meiner eigenen Erfahrung im Entwickeln von Vereinsplattformen weiß ich außerdem, dass diese Unterteilung “nicht alles” ist. Da geht es in der Regel eher um “Kinder männlich/weiblich”, “Junioren männlich/weiblich”, “Erwachsene männlich/weiblich” und “Senioren männlich/weiblich”, wobei sich auch das von Zeit zu Zeit ändert. Das lagert man am besten samt Definitionen in eine gesonderte Tabelle aus. Oh, und einmal heißen die Spalten “bol_maennlich” und einmal “bol_m” - wie denn nun? :wink:

Bei Verwendung von REAL solltest du dir bewusst sein, dass du statt 7.9 auch mal 7.8999999 zurückbekommen kannst … fängt dein Code das ab?

So, ich höre mal auf hier :wink: