web-dev-qa-db-ja.com

varchar文字列を数値として順序付けます

Postgres 8.3でvarchar列をintegerにキャストして結果行を並べることはできますか?

40
Jauzsika

絶対に可能です。

_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_でテストします。

97

また、フロートに変換可能なものがあるテキスト列で並べ替える場合は、次のようにします。

select * 
from your_table
order by cast(your_text_column as double precision) desc;
4
Eric Leschinski