Il carattere jolly PostgreSQL MI PIACE per qualsiasi elenco di parole


156

Ho un semplice elenco di ~ 25 parole. Ho un campo varchar in PostgreSQL, diciamo che l'elenco è ['foo', 'bar', 'baz']. Voglio trovare qualsiasi riga nella mia tabella che abbia una di quelle parole. Funzionerà, ma vorrei qualcosa di più elegante.

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

Risposte:


166

Puoi utilizzare l' SIMILAR TOoperatore di Postgres che supporta le alternanze, ad es

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

1
Regex potrebbe accelerare un po 'questo: dba.stackexchange.com/questions/10694/…
circa il

Come lo sai ? la maggior parte della documentazione che ho letto dice che i regex sono più lenti e un LIKE% ...
DestyNova,

5
Secondo dba.stackexchange.com/a/10696/27757 SIMILAR TO è tradotto internamente in una ricerca regex
Mark K Cowan,

Penso che l'uso lower()sia inefficace perché prima convertirà ogni stringa in minuscolo, il che è più costoso di una semplice corrispondenza senza maiuscole / minuscole
gilad mayani,

229

PostgreSQL supporta anche espressioni regolari POSIX complete :

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

Il ~*è una tra maiuscole e minuscole, ~maiuscole e minuscole.

Un'altra opzione è utilizzare QUALSIASI :

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

Puoi usare QUALSIASI con qualsiasi operatore che produca un valore booleano. Ho il sospetto che le opzioni di regex sarebbero più veloci ma QUALSIASI è uno strumento utile da avere nella tua cassetta degli attrezzi.


È interessante notare che, sebbene entrambi questi metodi siano più eleganti della soluzione di @chmullig (quindi +1), quando si verificano almeno 3 opzioni, eseguono significativamente più lentamente su tabelle di grandi dimensioni (91,5 milioni di record nel mio caso). Stavo vedendo un aumento del tempo di circa 2x quando ho usato uno di questi. Qualche idea sul perché potrebbe essere?
sage88,

@ sage88 Non lo so, ma Erwin Brandstetter potrebbe e l'aggiunta di indici di trigramma potrebbe aiutare.
mu è troppo corto il

13

In realtà esiste un operatore per questo in PostgreSQL:

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


Quindi ilike può essere usato con qualsiasi & array allo stesso modo? Questo sembra pulito se non c'è bisogno di regex fantasia. O sarà tradotto in regex internamente comunque?
mlt

Questa è una buona domanda, leggere il documento non fornisce una risposta esplicita. SIMILAR TOsi converte in Regular Expression, l' ~operatore sta per POSIX Regular Expression, ma questo non è chiaro LIKE.
jlandercy,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.