PostgreSQL-Platzhalter LIKE für eine beliebige Liste von Wörtern

156

Ich habe eine einfache Liste von ~ 25 Wörtern. Ich habe ein Varchar-Feld in PostgreSQL, sagen wir, diese Liste ist ['foo', 'bar', 'baz']. Ich möchte eine Zeile in meiner Tabelle finden, die eines dieser Wörter enthält. Das wird funktionieren, aber ich hätte gerne etwas eleganteres.

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

Antworten:

165

Sie können den Postgres- SIMILAR TOOperator verwenden, der Alternativen unterstützt, d. H.

select * from table where lower(value) similar to '%(foo|bar|baz)%';
Nordischer Mainframe
quelle
1
Regex könnte dies etwas beschleunigen
ungefähr
Woher weißt du das ? Die meisten Dokumentationen, die ich gelesen habe, besagen, dass Regex langsamer sind und ein LIKE% ...
DestyNova
5
Laut dba.stackexchange.com/a/10696/27757 SIMILAR TO wird intern in eine Regex-Suche übersetzt
Mark K Cowan
Ich denke, die Verwendung lower()ist ineffektiv, da sie zuerst jede Zeichenfolge in Kleinbuchstaben umwandelt, was teurer ist als nur eine Übereinstimmung
ohne Berücksichtigung der
228

PostgreSQL unterstützt auch reguläre POSIX-Ausdrücke :

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

Das ~*ist für eine Übereinstimmung ohne Berücksichtigung der ~Groß- und Kleinschreibung.

Eine andere Option ist die Verwendung von ANY :

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

Sie können ANY mit jedem Operator verwenden, der einen Booleschen Wert ergibt. Ich vermute, dass die Regex-Optionen schneller wären, aber JEDES ist ein nützliches Werkzeug, das Sie in Ihrer Toolbox haben sollten.

mu ist zu kurz
quelle
Interessanterweise sind beide Methoden eleganter als die Lösung von @chmullig (also +1), aber wenn mindestens 3 Optionen aktiviert sind, werden sie in großen Tabellen (in meinem Fall 91,5 Millionen Datensätze) erheblich langsamer ausgeführt. Ich sah eine Zeitvergrößerung von ungefähr 2x, wenn ich eines von diesen verwendete. Irgendeine Idee warum das sein könnte?
sage88
@ sage88 Ich weiß es nicht genau, aber Erwin Brandstetter könnte es tun und das Hinzufügen von Trigrammindizes könnte helfen.
Mu ist zu kurz
13

Tatsächlich gibt es dafür in PostgreSQL einen Operator:

SELECT *
FROM table
WHERE lower(value) ~~ ANY('{%foo%,%bar%,%baz%}');
jlandercy
quelle
Kann ilike also mit jedem & array auf die gleiche Weise verwendet werden? Dies sieht sauber aus, wenn kein ausgefallener Regex erforderlich ist. Oder wird es trotzdem intern in Regex übersetzt?
Mlt
@mlt Das ist eine gute Frage, das Lesen des Dokuments liefert keine explizite Antwort. SIMILAR TOkonvertiert in regulären Ausdruck, ~Operator steht für POSIX Regular Expression, aber dies ist nicht klar für LIKE.
Jlandercy