web-dev-qa-db-ja.com

特定の文字で文字列を分割するSQL-Standard

私のSQLステートメントでは、文字「_」の文字列から部分文字列を抽出する必要があります。文字列は、たとえば「A_XXX」「AB_XXX」「ABC_XXXX」にすることができるため、抽出される部分文字列は「A」「AB」「ABC」のようになります。

Oracleでは、これはsubstr()関数とinstr()関数を使用すると簡単です。

select substr('AB_XXX', 1, instr('AB_XXX', '_')-1) as substring
from dual;

結果は次のようになります。

SUBSTRING
------------------------
AB

特定の部分文字列が文字列の配列に含まれているかどうかを確認するには、このクエリが必要です。

クエリ全体は次のようになります。

select 'AB_XXX' from dual
where (instr('ABC_AB_A', substr('AB_XXX', 1, instr('AB_XXX', '_')-1))>0);

SQL-Standardでそれを書く方法はありますか?

よろしくお願いします。

編集:

PostgreSQLが代替機能を提供する場合、それも役立ちます。残りは、例えばで解決することができます。に。本当に重要な部分は、部分文字列を取得することです。

9
user3906778

2番目の例は、_'ABC_AB_A'_と_'AB_XXX'_を混在させているため、少し混乱しています。これがタイプミスかどうかはわかりません。

ただし、最初の___の前にすべての文字が必要な場合は、Postgresで次のように機能します。

_left(col, strpos(col, '_') - 1)
_

または正規表現を使用する:

_substring(col from '([A-Z]+)(_{1})')
_

Oracleでも正規表現を使用できます。

_regexp_substr(col, '([A-Z]+)(_{1})', 1, 1, 'i', 1)
_

Postgresのsubstring関数は常に正規表現の最初のキャプチャグループを返しますが、Oracleでは必要なグループを指定できます。これはregexp_substr()関数の最後のパラメータです。

SQLFiddle for Oracle: http://sqlfiddle.com/#!4/b138c/1
Postgres用SQLFiddle: http://sqlfiddle.com/#!15/4b2bb/1

17

標準のSQL文字列関数については、 SQL文字列関数と演算子 で説明しています。

関数呼び出しをネストすることなく、コンテンツを直接抽出できるsubstring関数があります。詳細は パターンマッチング として:

3つのパラメーターsubstring(エスケープ文字のパターンからの文字列)を持つ部分文字列関数は、SQL正規表現パターンに一致する部分文字列の抽出を提供します。 SIMILAR TOと同様に、指定されたパターンはデータ文字列全体と一致する必要があります。一致しない場合、関数は失敗し、nullを返します。成功時に返されるパターンの部分を示すには、パターンにエスケープ文字が2回出現し、その後に二重引用符( ")が続く必要があります。これらのマーカー間のパターンの部分に一致するテキストが返されます。

あなたの場合:

_select substring('AB_XX' from '#"%#"#_%' for '#');
_

結果:

部分文字列
 ----------- 
 AB 
(1行)

特に___は1文字のワイルドカードであるため、引用符で囲む必要があるため、構文は少し奇妙ですが、これはSQL標準です。

より多くの人が使用する構文については、regexp_replace()またはPOSIX正規表現で動作する同様の関数を検討してください。

2
Daniel Vérité

tl; dr

これのために意図的に構築された _split_part_ を使用します。

_split_part(string, '_', 1)
_

説明

これを引用する APIドキュメント

SPLIT_PART()関数は、指定された区切り文字で文字列を分割し、n番目の部分文字列を返します。

3つのパラメーターは、分割される文字列、区切り文字、および返される部分/部分文字列番号(1から始まる)です。

したがって、_AB_XXX_のようなものを含むstringという名前のフィールドがあり、___の前にすべてを取得したい場合は、それで分割して最初の部分/部分文字列を取得します。split_part(string, '_', 1)

2
totymedli