単語のリストのいずれかに対するPostgreSQLワイルドカードLIKE


156

約25語の簡単なリストがあります。PostgreSQLにvarcharフィールドがあります['foo', 'bar', 'baz']。リストがだとしましょう。これらの単語のいずれかが含まれているテーブル内の行を見つけたい。これでうまくいきますが、もっとエレガントなものが欲しいです。

select *
from table
where (lower(value) like '%foo%' or lower(value) like '%bar%' or lower(value) like '%baz%')

回答:


166

SIMILAR TO代替をサポートするPostgresの演算子を使用できます。

select * from table where lower(value) similar to '%(foo|bar|baz)%';

1
:正規表現は少しこれをスピードアップするかもしれませんdba.stackexchange.com/questions/10694/...
approxiblue

どうやってそれを知っていますか?私が読んだほとんどのドキュメントでは、正規表現は遅く、LIKE%...
DestyNova

5
dba.stackexchange.com/a/10696/27757に よるSIMILAR TOと、内部的に正規表現検索に変換されます
Mark K Cowan

lower()最初に各文字列を小文字に変換するため、使用すると効果がないと思います。大文字と小文字を区別しない一致よりもコストが高くなります
gilad mayani

229

PostgreSQLは、完全なPOSIX正規表現もサポートしています

select * from table where value ~* 'foo|bar|baz';

~*大文字小文字を区別しないマッチングのためで、~大文字と小文字が区別されます。

別のオプションはANYを使用することです:

select * from table where value  like any (array['%foo%', '%bar%', '%baz%']);
select * from table where value ilike any (array['%foo%', '%bar%', '%baz%']);

ブール値を生成する任意の演算子でANYを使用できます。正規表現オプションの方が速いと思いますが、いずれもツールボックスに含めると便利なツールです。


興味深いことに、これらの方法はどちらも@chmulligの解決策(+1)よりもエレガントですが、少なくとも3つのオプションをチェックすると、大きなテーブル(私の場合は9150万レコード)で実行が大幅に遅くなります。これらのいずれかを使用すると、約2倍の時間の増加がありました。なぜそうなるのでしょうか?
sage88

@ sage88頭の上ではわからないが、Erwin Brandstetterの可能性があり、トライグラムインデックスを追加すると役立つ場合があります。
muが短すぎる

13

実際、PostgreSQLにはそのための演算子があります。

SELECT *
FROM table
WHERE lower(value) ~~ ANY('{%foo%,%bar%,%baz%}');


だからは同じように任意の&配列で使用できますか?凝った正規表現が必要ない場合、これはきれいに見えます。それともとにかく内部的に正規表現に翻訳されますか?
mlt

@mltこれは良い質問です。ドキュメントを読んでも明確な答えは得られません。SIMILAR TO正規表現に変換され~ませんLIKE。演算子はPOSIX正規表現を表しますが、これはについては明確ではありません。
jlandercy

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.