0

を含む SQL クエリがあります。

REGEXP_REPLACE(LISTAGG(foo.name, ',') WITHIN GROUP (ORDER BY foo.name), '([^,]+)(,\1)+', '\1') AS bar

その中にSELECTLISTAGGfoo.name 列の値を区切り文字として「,」で連結し、REGEXP_REPLACE重複を置き換えます。

「,」(コンマの後に空白文字が続く) がセパレーターとして使用されるように を変更した場合、?LISTAGGをどのように調整する必要がありREGEXP_REPLACEますか?

編集:

をに変更するREGEXP_REPLACE'([^,]+)(, \1)+'、うまくいくようで、

シトロネンサウレ、カリウムソルバット、ペクチン

しかし、 を に変更するREGEXP_REPLACEと、'^([^,]+)(, \1)+$'まだ重複があります:

CITRONENSÄURE、CITRONENSÄURE、CITRONENSÄURE、CITRONENSÄURE、CITRONENSÄURE、KALIUMSORBAT、KALIUMSORBAT、KALIUMSORBAT、KALIUMSORBAT、KALIUMSORBAT、ペクチン、ペクチン、ペクチン、ペクチン、ペクチン

それで、'([^,]+)(, \1)+'ないに関係なく、正しいものですか^$?

4

1 に答える 1

1

で行ったのとまったく同じようLISTAGGに、コンマの後にスペースを追加します

'([^,]+)(, \1)+'

^ただし、文字列の先頭 ( ) と末尾 ( )に固定して、文字列全体に一致することを確認する必要があります$

'^([^,]+)(, \1)+$'


編集:
正規表現の構文については、質問の編集に答えるために、同じ行内の重複を削除する場合は、値全体が一致していることを確認する必要があります。たとえば、'([^,]+)(, \1)+'に一致し'fo[o], [o]ther'ます。そのため、末尾のカンマ (または文字列の末尾) も一致させます。

([^,]+), (\1(, |$))+

この式は、使用しようとしていたものよりもはるかに安全です。ただし、失敗する可能性があるいくつかのケースがあります。

SQL:

select regexp_replace(
    listagg("name", ', ') within group (order by "name")
    ,'([^,]+), (\1(, |$))+', '\1\3')
as "bar"
from foo;

SQLfiddle のデモ



いつ失敗する可能性がありますか?
最初の単語が固定されていないため、式は 100% 安全ではなく、値の途中で一致する可能性があります。たとえばWORD、リストから削除します。

'AWORD, WORD, XXX'  ==>  'AWORD, XXX'
  ====--^^^^--

Oracle は POSIX ERE を実装しており、ルックアラウンド、単語境界、アサーションをサポートしていないため、これを回避する方法はないと思います\G。さらに、これは重複した値を削除する適切な方法ではありません。非常に長いテーブルでは、ORA-01489: result of string concatenation is too long.

GROUP BYその場合はorを使用することをお勧めしDISTINCTます。この記事でそれについて読むことができます: SQL/mysql - 個別/UNIQUE を選択しますが、すべての列を返しますか? .

于 2015-09-23T07:29:14.180 に答える