[解決済み] PostgreSQL での isnumeric()
2022-02-09 19:32:26
質問
SQL文の中で、与えられた文字列が数値(整数または浮動小数点)として解釈されるかどうかを判断する必要があります。以下のように。
SELECT AVG(CASE WHEN x ~ '^[0-9]*.?[0-9]*$' THEN x::float ELSE NULL END) FROM test
私は、Postgresの パターンマッチング が使えそうです。そこで ここ を使い、浮動小数点数を取り入れた。これが私のコードです。
WITH test(x) AS (
VALUES (''), ('.'), ('.0'), ('0.'), ('0'), ('1'), ('123'),
('123.456'), ('abc'), ('1..2'), ('1.2.3.4'))
SELECT x
, x ~ '^[0-9]*.?[0-9]*$' AS isnumeric
FROM test;
出力されます。
x | isnumeric
---------+-----------
| t
. | t
.0 | t
0. | t
0 | t
1 | t
123 | t
123.456 | t
abc | f
1..2 | f
1.2.3.4 | f
(11 rows)
ご覧の通り、最初の2項目(空文字列の
''
と唯一のピリオドである
'.'
) が数値型であると誤判定されます (実際はそうではありません)。今のところこれ以上近づけません。何か助言をお願いします。
更新情報 ベースは この回答 (とそのコメント)にパターンを合わせました。
WITH test(x) AS (
VALUES (''), ('.'), ('.0'), ('0.'), ('0'), ('1'), ('123'),
('123.456'), ('abc'), ('1..2'), ('1.2.3.4'), ('1x234'), ('1.234e-5'))
SELECT x
, x ~ '^([0-9]+[.]?[0-9]*|[.][0-9]+)$' AS isnumeric
FROM test;
どちらが与えるか。
x | isnumeric
----------+-----------
| f
. | f
.0 | t
0. | t
0 | t
1 | t
123 | t
123.456 | t
abc | f
1..2 | f
1.2.3.4 | f
1x234 | f
1.234e-5 | f
(13 rows)
科学的記数法や負の数の扱いに、今見るとまだ問題がありますね。
どのように解決するのですか?
お気づきのように、正規表現に基づく方法は、正しく行うことがほとんど不可能です。例えば、あなたのテストでは
1.234e-5
は有効な数字ではありませんが、実際には有効です。また、負の数も見逃しています。数字のように見えるものでも、それを格納しようとするとオーバーフローを起こすとしたらどうでしょう?
に実際にキャストしようとする関数を作成することをお勧めします。
NUMERIC
(または
FLOAT
を返し、タスクがそれを必要とする場合は
TRUE
または
FALSE
このキャストが成功したかどうかによって異なります。
このコードで関数
ISNUMERIC()
:
CREATE OR REPLACE FUNCTION isnumeric(text) RETURNS BOOLEAN AS $$
DECLARE x NUMERIC;
BEGIN
x = $1::NUMERIC;
RETURN TRUE;
EXCEPTION WHEN others THEN
RETURN FALSE;
END;
$$
STRICT
LANGUAGE plpgsql IMMUTABLE;
この関数をデータに対して呼び出すと、次のような結果が得られます。
WITH test(x) AS ( VALUES (''), ('.'), ('.0'), ('0.'), ('0'), ('1'), ('123'),
('123.456'), ('abc'), ('1..2'), ('1.2.3.4'), ('1x234'), ('1.234e-5'))
SELECT x, isnumeric(x) FROM test;
x | isnumeric
----------+-----------
| f
. | f
.0 | t
0. | t
0 | t
1 | t
123 | t
123.456 | t
abc | f
1..2 | f
1.2.3.4 | f
1x234 | f
1.234e-5 | t
(13 rows)
より正しく、読みやすいだけでなく、データが実際に数字であった場合、より速く動作します。
関連
-
[解決済み] アドレスフィールド検証のための正規表現
-
[解決済み] PostgreSQLの場合。PostgreSQLのテーブルを表示する
-
[解決済み] PostgreSQLの "DESCRIBE TABLE"
-
[解決済み] PostgreSQL コマンドラインユーティリティ: psql を終了する方法
-
[解決済み] PostgreSQLのユーザーパスワードを変更する方法を教えてください。
-
[解決済み] どのバージョンのPostgreSQLを使用していますか?
-
[解決済み] PostgreSQLからのPL/pgSQL出力をCSVファイルに保存する
-
[解決済み] PostgreSQLでデータベースのコピーを作成する
-
[解決済み】Mac OS XでPostgreSQLサーバーを起動するには?
-
[解決済み】PostgreSQLのエラーです。Fatal: ロール "username" が存在しません。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Vimで正規表現に置換すると、`E488: Trailing characters`が発生します。
-
[解決済み] Regex:最初に出現する文字までのマッチング
-
[解決済み] 正規表現による逆マッチ[重複]の場合
-
[解決済み] 最初のマッチで停止する正規表現
-
[解決済み] 与えられた文字列が与えられた部分文字列を含んでいるかどうかを見つけるための、scala の慣用的な方法は何ですか?
-
[解決済み] 小数点以下2桁までの値にマッチする正規表現
-
[解決済み] Atomで改行文字を置き換えるには?
-
[解決済み] この正規表現に負の小数点を含めるにはどうしたらよいですか?
-
[解決済み] 正規表現におけるバックスラッシュの後の数値の意味は?
-
[解決済み] Regex - 特定の文字が含まれていません。