Wobei Spalte nicht mehrere Werte mag

8

Ich versuche, Datensätze in einer Postgresql-Datenbank auszuwählen, in der der Benutzername nicht wie eine Liste von Zeichenfolgen ist.

SELECT * FROM rails_db WHERE username NOT LIKE 'j%' AND username NOT LIKE '%eepy%';

Das Problem ist, dass es viele dieser Werte gibt. Gibt es eine Möglichkeit, ein Array davon zu erstellen und etwas zu sagen wie:

SELECT * FROM rails_db WHERE username NOT LIKE ARRAY[my values];
Jeff
quelle

Antworten:

12

Sie hatten fast die richtige Syntax. Genau das wollen Sie:

SELECT * FROM rails_db WHERE username NOT LIKE ALL(ARRAY[my values]);

Dies ist eine sehr schöne Syntax, die jedoch nicht unbedingt schnell sein muss, insbesondere nicht, wenn das Array groß ist. Was Sie wollen, ist jedoch schwer für die Leistung zu optimieren, und es gibt keinen Grund zu der Annahme, dass hässlichere Syntaxen schneller sind.

jjanes
quelle
Was wäre, wenn ich eine temporäre Tabelle erstellen und stattdessen eine Verknüpfung herstellen würde? Wäre das schneller / effizienter?
Jeff
Ich denke nicht, dass eine temporäre Tabelle schneller wäre. Das Problem ist, dass ein "nicht wie" nicht wirklich indizierbar ist, und es gibt nicht viel, was das ändern kann. Die am besten zugängliche Form der Optimierung wäre möglicherweise, die selektivste Zeichenfolge (die die meisten Zeilen ausschließt) als erste in das Array / die Liste aufzunehmen.
Jjanes
1

Ich habe es vielleicht gefunden, aber ich möchte sehen, ob dies so funktioniert, wie es soll:

SELECT * FROM rails_db WHERE username !~* 'j.*|.*eepy.*';
Jeff
quelle
Dies scheint nicht zu funktionieren, wenn ich Dinge mit einem Punkt darin ausschließen möchte:'j.*|...|\.'
Jeff
1
Hier gibt es ein paar Missverständnisse. Ich habe eine weitere Antwort hinzugefügt.
Erwin Brandstetter
1

Ihre Idee, einen regulären Ausdruck mit Zweigen zu verwenden, ist solide. Aber in Ihrer Antwort haben Sie die Übersetzung des Sonderzeichens %in LIKEMuster falsch verstanden.

Diese:

... WHERE username NOT LIKE 'j%' AND username NOT LIKE '%eepy%';

wird übersetzt in:

... WHERE username !~ '^j|eepy';

!~unterscheidet zwischen Groß- und Kleinschreibung NOT LIKE.
Verwenden Sie !~*diese Option , um Groß- und Kleinschreibung zu berücksichtigen NOT ILIKE.
So schließen Sie auch Zeichenfolgen aus, die irgendwo einen Punkt ( .) enthalten , und ein anderes Beispiel, das mit dem Ende der Zeichenfolge übereinstimmt (nicht übereinstimmt), wie folgt username NOT LIKE '%end':

... WHERE username !~ '^j|end$|eepy|\.';

Wahrscheinlich auch nicht sehr schnell.

Erwin Brandstetter
quelle
0
with help(term) as (values('T%'),('STAG%'))
select tabschema, tabname
from syscat.indexes
where not exists (select 1 from help where tabschema like term)
Jürgen Götz
quelle