正規表現の一致を試み、失敗した場合はnull
を返します。
次のクエリは、文字列の最初の数値を見つけようとします。結果は、テキスト'blah'
のエントリを無視します。代わりにnull
値を返す方がいいです。
この質問は、おそらく正規表現についてではなく、集合代数についてです。私の直感は、グーグルが無駄であることを証明していますが、何もleft join
する必要なしに、エレガントな方法があることです。
with test_data as (
select 'abc 123' as txt
union
select 'abc 456' as txt
union
select 'blah' as txt
)
select
txt,
(regexp_matches(txt, '\d+'))[1] as first_num
from
test_data
あなたの答えがregexp_matches()
の問題を解決する一方で、avoidより適切な関数の問題 substring()
まずは次のとおりです。
_WITH test_data(txt) AS (
VALUES
(text 'abc 123')
, ('abc 456')
, ('blah')
)
SELECT txt, substring(txt FROM '\d+') AS first_num
FROM test_data;
_
文字列の最初の一致を返すか、またはno matchの場合はNULL
を返します。
substring(string FROM pattern)
は標準SQL構文です。
それをsubstring(string [FROM int] [FOR int])
またはsubstring(string FROM pattern FOR escape)
と混同しないでください。
短い、同等の、現在文書化されていないPostgres実装substring(text, text)
を使用することもできます(FROM
の代わりにコンマ(_,
_)を使用)。
regexp_matches()
を使用して、allの一致をsetとして返します。 (単一の正規表現では複数の一致が発生する可能性があるため、テキストのセットarrays)に注意してください。フラグ_'g'
_を追加してすべての行を取得しない限り、最初の行のみが引き続き取得されます(同じ正規表現に対して追加の一致がある場合は、それらを取得します)。関連:
複雑化を避けるために、Postgres 10より前のバージョンでは、セットを返す関数をFROM
リストに移動します。
または、Postgres 10以降で regexp_match()
を使用して、最初の行のみを返します。これも元の問題を示しません。
_WITH test_data(txt) AS (
VALUES
(text 'abc 123')
, ('abc 456')
, ('blah')
)
SELECT txt, (regexp_match(txt, '\d+'))[1] AS first_num
from test_data;
_
ただし、目的に応じてsubstring()
を使用してください。
db <> fiddle ここ
副選択を使用します。
the docs から:
副選択を使用することにより、regexp_matches()が常に1行を返すように強制することが可能です。これは、一致しない行も含めてすべての行を返す必要があるSELECTターゲットリストで特に役立ちます。
解決策は次のとおりです。
with test_data as (
select 'abc 123' as txt
union
select 'abc 456' as txt
union
select 'blah' as txt
)
select
txt,
(select regexp_matches(txt, '\d+'))[1] as first_num
from
test_data