それは絶対に可能です。
ORDER BY varchar_column::int
varchar
に有効な整数リテラルがあることを確認してください 各エントリの列、または例外invalid input syntax for integer: ...
。 (先頭と末尾の空白は問題ありません。自動的にトリミングされます。)
その場合は、列をinteger
に変換してみませんか。 そもそも?より小さく、より速く、よりクリーンで、よりシンプルに。
例外を回避する方法は?
キャストの前に数字以外の文字を削除して、発生する可能性のある例外を回避するには:
ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
-
regexp_replace()
式は数字以外のすべてを効果的に削除するため、数字のみが残るか、空の文字列になります。 (以下を参照してください。) -
\D
文字クラス[^[:digit:]]
の省略形です 、すべての非数字を意味します([^0-9]
)。
古い設定の古いPostgresバージョンではstandard_conforming_strings = off
、Posixエスケープ文字列構文E'\\D'
を使用する必要があります バックスラッシュをエスケープするには\
。これはPostgres8.3のデフォルトであったため、古いバージョンではこれが必要になります。 -
4番目のパラメータ
g
「グローバルに」用です 、すべてを置き換えるように指示する 最初だけでなく、発生。 -
あなたはかもしれません 先頭のダッシュを許可する(
-
)負の数の場合。 -
文字列に数字がまったくない場合、結果は空の文字列になり、
integer
へのキャストには無効になります。 。空の文字列をNULL
に変換しますNULLIF
を使用 。 (0
を検討するかもしれません 代わりに。)
結果は有効であることが保証されています。この手順は、integer
へのキャスト用です 質問の本文で要求されているように、numeric
ではありません タイトルにあるように。
高速化するには?
1つの方法は、式のインデックスです。
CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));
次に、ORDER BY
で同じ式を使用します 条項:
ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)
EXPLAIN ANALYZE
でテストする 機能インデックスが実際に使用されるかどうか。