Curinga do PostgreSQL COMO para uma lista de palavras


156

Eu tenho uma lista simples de ~ 25 palavras. Eu tenho um campo varchar no PostgreSQL, digamos que a lista seja ['foo', 'bar', 'baz']. Quero encontrar qualquer linha na minha tabela que contenha alguma dessas palavras. Isso vai funcionar, mas eu gostaria de algo mais elegante.

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

Respostas:


166

Você pode usar o SIMILAR TOoperador do Postgres que suporta alternações, ou seja,

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

1
O Regex pode acelerar um pouco isso: dba.stackexchange.com/questions/10694/…
approxiblue

Como você sabe ? a maior parte da documentação que li diz que o regex é mais lento e
semelhante a

5
De acordo com dba.stackexchange.com/a/10696/27757, SIMILAR TO é traduzido internamente para uma pesquisa regex
Mark K Cowan

Acho que usando lower()é ineficaz porque ele vai primeiro converter cada cadeia para minúsculas, que é mais caro do que apenas uma combinação case-insensitive
gilad Mayani

229

O PostgreSQL também suporta expressões regulares completas do POSIX :

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

O ~*é para uma correspondência que não diferencia maiúsculas de minúsculas, diferencia ~maiúsculas de minúsculas.

Outra opção é usar QUALQUER :

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

Você pode usar QUALQUER com qualquer operador que produz um booleano. Eu suspeito que as opções de regex seriam mais rápidas, mas QUALQUER é uma ferramenta útil para ter em sua caixa de ferramentas.


Curiosamente, embora esses dois métodos sejam mais elegantes que a solução do @chmullig (portanto +1), ao marcar três opções pelo menos, eles são executados significativamente mais lentamente em tabelas grandes (91,5 milhões de registros no meu caso). Eu estava vendo um aumento de tempo de cerca de 2x ao usar um desses. Alguma idéia do porquê disso?
precisa saber é

@ sage88 Não sei de nada, mas Erwin Brandstetter pode e adicionar índices de trigramas pode ajudar.
mu é muito curto

13

Na verdade, existe um operador para isso no PostgreSQL:

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


Assim, o ilike pode ser usado com qualquer & array da mesma maneira? Parece limpo se não houver necessidade de regex sofisticado. Ou será traduzido para regex internamente?
mlt

@ mlt Essa é uma boa pergunta, a leitura do documento não fornece uma resposta explícita. SIMILAR TOconverter em Expressão regular, o ~operador significa Expressão regular POSIX, mas isso não está claro LIKE.
jlandercy

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.