PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Bestellen Sie die varchar-Zeichenfolge als numerisch

Es ist absolut möglich.

ORDER BY varchar_column::int

Stellen Sie sicher, dass Ihr varchar gültige Integer-Literale enthält Spalte für jeden Eintrag oder Sie erhalten eine Ausnahme invalid input syntax for integer: ... . (Leerraum am Anfang und am Ende ist ok - er wird automatisch gekürzt.)

Wenn dies jedoch der Fall ist, warum konvertieren Sie die Spalte dann nicht in integer zunächst? Kleiner, schneller, sauberer, einfacher.

Wie vermeide ich Ausnahmen?

Um nicht-stellige Zeichen vor der Umwandlung zu entfernen und dadurch mögliche Ausnahmen zu vermeiden:

ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
  • Der regexp_replace() expression entfernt effektiv alle Nicht-Ziffern, sodass nur Ziffern oder eine leere Zeichenfolge übrig bleiben. (Siehe unten.)

  • \D ist eine Abkürzung für die Zeichenklasse [^[:digit:]] , also alle Nichtziffern ([^0-9] ).
    In alten Postgres-Versionen mit der veralteten Einstellung standard_conforming_strings = off , müssen Sie die Posix-Escape-String-Syntax E'\\D' verwenden um den Backslash \ zu maskieren . Dies war die Standardeinstellung in Postgres 8.3, also brauchen Sie das für Ihre veraltete Version.

  • Der 4. Parameter g steht für "global" , die anweist, alle zu ersetzen Ereignisse, nicht nur das erste.

  • Sie können einen führenden Bindestrich zulassen möchten (- ) für negative Zahlen.

  • Wenn der String überhaupt keine Ziffern enthält, ist das Ergebnis ein leerer String, der für eine Umwandlung in integer nicht gültig ist . Konvertieren Sie leere Zeichenfolgen in NULL mit NULLIF . (Sie könnten 0 in Betracht ziehen stattdessen.)

Das Ergebnis ist garantiert valide. Dieses Verfahren ist für eine Umwandlung in integer wie im Hauptteil der Frage gefordert, nicht für numeric wie der Titel schon sagt.

Wie macht man es schnell?

Eine Möglichkeit ist ein Index für einen Ausdruck.

CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));

Verwenden Sie dann denselben Ausdruck in ORDER BY Klausel:

ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)

Testen Sie mit EXPLAIN ANALYZE ob der funktionale Index tatsächlich verwendet wird.