MySQL LIKE IN ()?

273

Meine aktuelle Anfrage sieht folgendermaßen aus:

SELECT * FROM fiberbox f WHERE f.fiberBox LIKE '%1740 %' OR f.fiberBox LIKE '%1938 %' OR f.fiberBox LIKE '%1940 %'

Ich habe mich ein bisschen umgesehen und kann nichts Ähnliches wie ein LIKE IN () finden - ich stelle mir vor, dass es so funktioniert:

SELECT * FROM fiberbox f WHERE f.fiberbox LIKE IN('%140 %', '%1938 %', '%1940 %')

Irgendwelche Ideen? Denke ich nur falsch über das Problem nach - einen obskuren Befehl, den ich noch nie gesehen habe.

MySQL 5.0.77-Community-Protokoll

Michael Wales
quelle
1
WHERE FIND_IN_SET(f.fiberbox, "1740,1938,1940")
Gjermund Dahl
2
FIND_IN_SET akzeptiert keine Platzhalter wie%
Sebastián Grignoli

Antworten:

453

Ein REGEXP mag effizienter sein, aber Sie müssten es vergleichen, um sicherzugehen, z

SELECT * from fiberbox where field REGEXP '1740|1938|1940'; 
Paul Dixon
quelle
2
Ich mag diese Antwort - schnell, einfach, habe alle "Optionen" in einer Zeile wie ich wollte (einfach zu bearbeiten). Bei der kleinen Ergebnismenge, die ich anstrebe, gibt es überhaupt keinen Leistungsabfall.
Michael Wales
51
Über 1 Million Zeilen in meiner Tabelle. REGEX um 0,0009 und LIKE um 0,0005. Wenn mehr als 5 REGEX, um 0,0012 ...
David Bélanger
10
Ich hatte ein Problem, das REGEXPunerschwinglich langsam war, aber ich brauchte die Flexibilität von REGEXP, um meine Ergebnismenge weiter einzugrenzen, als es LIKEmöglich war. Ich habe eine Hybridlösung entwickelt, bei der ich beide LIKEund REGEXP; Obwohl der REGEXPAnteil ausreicht, um die richtigen Ergebnisse zu LIKEerzielen, konnte MySQL mit MySQL die Ergebnismenge erheblich reduzieren, bevor die langsameren REGEXPKriterien verwendet werden mussten.
Mpen
1
So erhalten Sie den regulären Ausdruckswert aus einer Spalte:(select group_concat(myColumn separator '|') from..)
daVe
5
Hinzufügen zu den Leistungsdaten. Unter MySql 5.5 in einer Tabelle mit 229 Millionen Zeilen ist ein 1-Begriff-Link mit 3 Zeichen verankert: REGEXP: 16s, LIKE: 8.5s; 2 Begriffe: REGEXP: 22,1 s, LIKE: 9,69; '^ (Hämoglobin | hematr? ocrit). *' vs 3 Begriff wie: REGEXP: 36,3, LIKE: 9,59.
Jesse Clark
181

Paul Dixons Antwort hat bei mir hervorragend funktioniert. Um dies hinzuzufügen, sind hier einige Dinge, die ich für diejenigen beobachtet habe, die an der Verwendung von REGEXP interessiert sind:

So führen Sie mehrere LIKE-Filter mit Platzhaltern durch:

 SELECT * FROM fiberbox WHERE field LIKE '%1740 %'
                           OR field LIKE '%1938 %'
                           OR field LIKE '%1940 %';  

Verwenden Sie REGEXP Alternative:

 SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 |1940 ';

Werte in REGEXP-Anführungszeichen und zwischen | (ODER-) Operatoren werden als Platzhalter behandelt. In der Regel benötigt REGEXP Platzhalterausdrücke wie (. *) 1740 (. *), Um als% 1740% zu arbeiten.

Wenn Sie mehr Kontrolle über die Platzierung des Platzhalters benötigen, verwenden Sie einige der folgenden Varianten:

So erreichen Sie LIKE mit kontrollierter Platzhalterplatzierung:

SELECT * FROM fiberbox WHERE field LIKE '1740 %'
                          OR field LIKE '%1938 '
                          OR field LIKE '%1940 % test';  

Verwenden:

SELECT * FROM fiberbox WHERE field REGEXP '^1740 |1938 $|1940 (.*) test';
  • Wenn Sie ^ vor den Wert stellen, wird der Zeilenanfang angezeigt.

  • Wenn Sie $ nach dem Wert platzieren, wird das Zeilenende angezeigt.

  • Das Platzieren (. *) Verhält sich ähnlich wie der Platzhalter%.

  • Das . Gibt ein einzelnes Zeichen mit Ausnahme von Zeilenumbrüchen an. Platzieren. inside () mit * (. *) fügt ein sich wiederholendes Muster hinzu, das eine beliebige Anzahl von Zeichen bis zum Zeilenende angibt.

Es gibt effizientere Möglichkeiten, bestimmte Übereinstimmungen einzugrenzen, dies erfordert jedoch eine genauere Überprüfung der regulären Ausdrücke. HINWEIS: Nicht alle Regex-Muster scheinen in MySQL-Anweisungen zu funktionieren. Sie müssen Ihre Muster testen und sehen, was funktioniert.

So führen Sie mehrere LIKE- und NOT LIKE-Filter durch:

SELECT * FROM fiberbox WHERE field LIKE '%1740 %'
                          OR field LIKE '%1938 %'
                          OR field NOT LIKE '%1940 %'
                          OR field NOT LIKE 'test %'
                          OR field = '9999';

Verwenden Sie REGEXP Alternative:

SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 |^9999$'
                          OR field NOT REGEXP '1940 |^test ';

ODER gemischte Alternative:

SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 '
                          OR field NOT REGEXP '1940 |^test '
                          OR field NOT LIKE 'test %'
                          OR field = '9999';

Beachten Sie, dass ich das NOT-Set in einem separaten WHERE-Filter getrennt habe. Ich experimentierte mit Negationsmustern, vorausschauenden Mustern und so weiter. Diese Ausdrücke schienen jedoch nicht die gewünschten Ergebnisse zu liefern. Im ersten Beispiel oben verwende ich ^ 9999 $, um die genaue Übereinstimmung anzuzeigen. Auf diese Weise können Sie bestimmte Übereinstimmungen mit Platzhalterübereinstimmungen im selben Ausdruck hinzufügen. Sie können diese Arten von Anweisungen jedoch auch mischen, wie Sie im zweiten aufgeführten Beispiel sehen können.

In Bezug auf die Leistung habe ich einige kleinere Tests mit einer vorhandenen Tabelle durchgeführt und keine Unterschiede zwischen meinen Variationen festgestellt. Ich stelle mir jedoch vor, dass die Leistung bei größeren Datenbanken, größeren Feldern, größeren Datensatzzahlen und komplexeren Filtern ein Problem darstellen könnte.

Verwenden Sie wie immer die obige Logik, da dies sinnvoll ist.

Wenn Sie mehr über reguläre Ausdrücke erfahren möchten, empfehle ich www.regular-expressions.info als gute Referenzseite.

David Carroll
quelle
Beachten Sie, dass ein Feld mit dem Wert NULL nicht mit REGEXP übereinstimmt. Sie können IFNULL verwenden, um dieses Problem zu lösen. WHERE IFNULL(field, '') NOT REGEXP '1740 | 1938'
@DanyMarcoux Was ist, wenn ich (. *) Verwenden möchte, aber es sollte sich wie FIELDNAME LIKE '%%' verhalten, wie man es mit regulärem Ausdruck verwendet, damit, wenn eine leere Zeichenfolge übergeben wird. es sollte alle Aufzeichnungen
abrufen
Das WHERE-Feld NOT LIKE '% 1940%' ODER das Feld NOT LIKE 'test%' gibt immer alle Zeilen zurück. Das hat vielleicht dazu beigetragen, dass Sie nicht die gewünschten Ergebnisse erzielt haben, die Sie erwähnt haben?
Herbert Van-Vliet
14

Sie können eine Inline-Ansicht oder eine temporäre Tabelle erstellen, diese mit Ihren Werten füllen und Folgendes ausgeben:

SELECT  *
FROM    fiberbox f
JOIN    (
        SELECT '%1740%' AS cond
        UNION ALL
        SELECT '%1938%' AS cond
        UNION ALL
        SELECT '%1940%' AS cond
        ) с
ON      f.fiberBox LIKE cond

Dies kann jedoch dazu führen, dass Sie mehrere Zeilen für eine fiberboxsolche Zeile zurückgeben '1740, 1938', sodass diese Abfrage besser zu Ihnen passt:

SELECT  *
FROM    fiberbox f
WHERE   EXISTS
        (
        SELECT  1
        FROM    (
                SELECT '%1740%' AS cond
                UNION ALL
                SELECT '%1938%' AS cond
                UNION ALL
                SELECT '%1940%' AS cond
                ) с
        WHERE   f.fiberbox LIKE cond
        )
Quassnoi
quelle
13

Regexp Weg mit Werteliste

SELECT * FROM table WHERE field regexp concat_ws("|",
"111",
"222",
"333");
user136379
quelle
7

Entschuldigung, es gibt keine ähnliche Operation wie LIKE INin MySQL.

Wenn Sie den Operator LIKE ohne Join verwenden möchten, müssen Sie dies folgendermaßen tun:

(field LIKE value OR field LIKE value OR field LIKE value)

Sie wissen, MySQL wird diese Abfrage nicht optimieren, FYI.

gahooa
quelle
4

Beachten Sie einfach jeden, der versucht, mit dem REGEXP die "LIKE IN" -Funktionalität zu verwenden.

Mit IN können Sie Folgendes tun:

field IN (
'val1',
'val2',
'val3'
)

In REGEXP funktioniert dies nicht

REGEXP '
val1$|
val2$|
val3$
'

Es muss in einer Zeile wie dieser stehen:

REGEXP 'val1$|val2$|val3$'
Shaakir
quelle
3

Operanden spiegeln

'a,b,c' like '%'||field||'%'
Ed Heal
quelle
2
Wenn Sie ein Feld haben, würde dies explizit etwas bedeuten, z. Eine Aufzählung für Absolventen 'a', 'b', 'c', aber nicht ab, ac oder bc create table x(en enum('a,b,c')));insert into x values('a'),('b') en ist nur a oder b. Diese Methode durch Umdrehen von Oprands select * from, x where 'a,c' like concat('%',en,'%')kann in SQL Injunction sicherer sein, ohne dass Zeichen wie $ ^ usw.
Dies ist NICHT gleichwertig und funktioniert nicht für allgemeine Fälle. Wenn Sie wüssten, dass fielddas nur genau sein kann a, boder cdann sollten Sie verwenden field IN ('a', 'b', 'c'). Aber im allgemeinen Fall kann dies nie ersetzen , field LIKE '%a%' OR field LIKE '%b%' OR ...weil Feld selbst so etwas wie sein kann , magicder würde 'magic' LIKE '%a%'wahr , aber der Ausdruck 'a,b,c' LIKE '%magic%'falsch.
ADTC
2

Das wäre richtig:

SELECT * FROM table WHERE field regexp concat_ws("|",(
"111",
"222",
"333"
));
Edmhs
quelle
2

Nur ein kleiner Tipp:

Ich bevorzuge die Variante RLIKE (genau der gleiche Befehl wie REGEXP ), da sie eher nach natürlicher Sprache klingt und kürzer ist. Nun, nur 1 Zeichen.

Das Präfix "R" steht für Reg. Exp. Natürlich.

Raúl Moreno
quelle
0

Sie können das gewünschte Ergebnis mit Hilfe von regulären Ausdrücken erhalten .

SELECT fiberbox from fiberbox where fiberbox REGEXP '[1740|1938|1940]';

Wir können die obige Abfrage testen, bitte klicken Sie auf SQL-Geige

SELECT fiberbox from fiberbox where fiberbox REGEXP '[174019381940]';

Wir können die obige Abfrage testen, bitte klicken Sie auf SQL-Geige

ZIJ
quelle
1
Dies ist ein falscher regulärer Ausdruck. [...]ist ein Zeichensatz , was bedeutet, dass alle Zeichen im Satz ausreichen, um als Übereinstimmung angesehen zu werden. Also jeden Wert mit den Ziffern ' 0, 1, 3, 4, 7, 8, 9oder das |Pipe - Zeichen wird dieses Spiel.
Martijn Pieters