Postgres 8.3でvarchar
列をinteger
にキャストして結果行を並べることはできますか?
絶対に可能です。
_ORDER BY varchar_column::int
_
varchar
列に有効な整数リテラルがあることを確認してください。そうしないと、例外が発生します。 (先頭および末尾の空白は問題ありません。自動的に削除されます。)
ただし、その場合は、列をinteger
に変換して始めてみませんか?より小さく、より速く、よりきれいに、よりシンプルに。
キャストの前に数字以外の文字を削除して、可能な例外を回避するには:
_ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
_
regexp_replace()
式は、すべての非数字を効果的に削除するため、数字のみまたは空の文字列のみが残ります。 (下記参照。)
_\D
_は、文字クラス_[^[:digit:]]
_の省略形であり、すべての非数字(_[^0-9]
_)を意味します。
古い設定_standard_conforming_strings = off
_を使用した古いPostgresバージョンでは、バックスラッシュ_E'\\D'
_をエスケープするためにPosixエスケープ文字列構文_\
_を使用する必要があります。これはPostgres 8.3のデフォルトでしたので、古いバージョンにはこれが必要になります。
4番目のパラメーターg
は "globally" に対応し、最初のオカレンスだけでなく all オカレンスを置き換えるように指示します。
は、負の数に先頭のダッシュ(_-
_)を許可したい場合があります。
文字列に数字がない場合、結果は空の文字列になり、integer
へのキャストには無効になります。 NULL
を使用して、空の文字列をNULLIF
に変換します。 (代わりに_0
_を検討できます。)
結果は有効であることが保証されています。この手順は、integer
へのキャスト用で、質問の本文で要求されているとおりです。ではなく、numeric
タイトルが言及しています。
1つの方法は、 式のインデックス です。 (マニュアルバージョン8.3へのリンク。)
_CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, E'\\D', '', 'g'), '') AS integer));
_
次に、_ORDER BY
_句で同じ式を使用します。
_ORDER BY
cast(NULLIF(regexp_replace(varchar_column, E'\\D', '', 'g'), '') AS integer)
_
関数インデックスが実際に使用されるかどうかを_EXPLAIN ANALYZE
_でテストします。
また、フロートに変換可能なものがあるテキスト列で並べ替える場合は、次のようにします。
select *
from your_table
order by cast(your_text_column as double precision) desc;