PostgreSQL comodín COMO para cualquiera de una lista de palabras

156

Tengo una lista simple de ~ 25 palabras. Tengo un campo varchar en PostgreSQL, digamos que la lista es ['foo', 'bar', 'baz']. Quiero encontrar cualquier fila en mi tabla que tenga alguna de esas palabras. Esto funcionará, pero me gustaría algo más elegante.

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

Respuestas:

166

Puede usar el SIMILAR TOoperador de Postgres que admite alternancias, es decir

select * from table where lower(value) similar to '%(foo|bar|baz)%';
Mainframe nórdico
fuente
1
Regex podría acelerar esto un poco: dba.stackexchange.com/questions/10694/…
aproximadamente el
Como lo sabes ? la mayor parte de la documentación que he leído dice que las expresiones regulares son más lentas y un% ME GUSTA ...
DestyNova
55
De acuerdo con dba.stackexchange.com/a/10696/27757 SIMILAR TO se traduce internamente a una búsqueda de expresiones regulares
Mark K Cowan
Creo que el uso lower()es ineficaz porque primero se convertirá cada cadena a minúsculas, lo que es más costoso que solamente un partido entre mayúsculas y minúsculas
Gilad Mayani
229

PostgreSQL también admite expresiones regulares POSIX completas :

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

El ~*es para una coincidencia entre mayúsculas y minúsculas, ~es sensible a mayúsculas y minúsculas

Otra opción es usar CUALQUIERA :

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

Puede usar CUALQUIERA con cualquier operador que produzca un valor booleano. Sospecho que las opciones de expresiones regulares serían más rápidas, pero CUALQUIERA es una herramienta útil para tener en su caja de herramientas.

mu es demasiado corto
fuente
Curiosamente, si bien ambos métodos son más elegantes que la solución de @chmullig (por lo tanto, +1), al marcar 3 opciones al menos, se ejecutan significativamente más lento en tablas grandes (91,5 millones de registros en mi caso). Estaba viendo un aumento de tiempo de aproximadamente 2 veces al usar cualquiera de estos. ¿Alguna idea de por qué podría ser eso?
sage88
@ sage88 No lo sé, pero podría ayudar Erwin Brandstetter y agregar índices de trigrama .
mu es demasiado corto el
13

En realidad, hay un operador para eso en PostgreSQL:

SELECT *
FROM table
WHERE lower(value) ~~ ANY('{%foo%,%bar%,%baz%}');
jlandercy
fuente
66
~~es sólo otro nombre para like: "El operador ~~es equivalente a LIKE, y ~~*corresponde a ILIKEExisten también. !~~y !~~*operadores que representan NOT LIKEy NOT ILIKE, respectivamente Todos estos operadores son PostgreSQL-específica.". . Y '{%foo%,%bar%,%baz%}'es la forma de texto de array['%foo%', '%bar%', '%baz%'].
mu es demasiado corto el
Así puede iLike usarse con cualquier y variedad de la misma manera? Esto se ve limpio si no hay necesidad de expresiones regulares sofisticadas. ¿O se traducirá a regex internamente de todos modos?
mlt
@mlt Esa es una buena pregunta, leer el documento no proporciona una respuesta explícita. SIMILAR TOse convierte en expresión regular, el ~operador representa la expresión regular POSIX, pero esto no está claro LIKE.
jlandercy