MySQL LIKE IN()?


273

私の現在のクエリは次のようになります:

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

私は周りを見回しましたが、LIKE IN()に似たものを見つけることができませんでした-私はそれが次のように機能することを想定しています:

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

何か案は?私は問題を間違った方法で考えているのでしょうか-私が見たことのないあいまいなコマンド。

MySQL 5.0.77-community-log


1
WHERE FIND_IN_SET(f.fiberbox, "1740,1938,1940")
Gjermund Dahl

2
FIND_IN_SETは次のようにワイルドカードを受け入れていない%
セバスティアンGrignoli

回答:


454

A REGEXPは あります、より効率的で、しかし、あなたはそれを確認するベンチマークに必要があるだろう、例えば

SELECT * from fiberbox where field REGEXP '1740|1938|1940'; 

2
私はこの答えが好きです-すばやく簡単に、すべての「オプション」を1行にまとめました(編集が簡単)。私が対象としている小さな結果セットでは、パフォーマンスの低下はまったくありません。
マイケルウェールズ

51
テーブルに100万行以上あります。REGEXは0.0009あたり、LIKEは0.0005あたりです。5以上の正規表現の場合、0.0012前後...
DavidBélanger

10
REGEXP非常に遅い問題がありましたが、結果セットをさらに絞り込むためにREGEXPの柔軟性が必要でしたLIKE提供できる範囲。私は両方を使用するハイブリッドソリューションを思い付いたLIKEREGEXPREGEXP正しい結果を得るにはこの部分で十分ですが、LIKEMySQLを使用すると、より遅いREGEXP基準を使用する必要がある前に、結果セットを大幅に削減できます。
mpen 2012

1
列から正規表現値を取得するには:(select group_concat(myColumn separator '|') from..)
daVe

5
パフォーマンスデータに追加します。行が229M行のテーブル内のMySql 5.5では、1項左アンカー3文字検索:REGEXP:16秒、LIKE:8.5秒。2項:REGEXP:22.1秒、LIKE:9.69; '^(hemoglobin | hematr?ocrit)。*' vs 3のような用語:REGEXP:36.3、LIKE:9.59。
Jesse Clark

181

ポール・ディクソンの答えは私にとって見事に機能しました。これに追加して、REGEXPの使用に関心のある人のために私が観察したいくつかのことを以下に示します。

ワイルドカードを使用して複数のLIKEフィルターを実行するには:

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

REGEXP代替を使用:

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

REGEXP引用符内および|の間の値 (OR)演算子はワイルドカードとして扱われます。通常、REGEXPが%1740%として機能するには、(。*)1740(。*)などのワイルドカード式が必要です。

ワイルドカードの配置をさらに制御する必要がある場合は、以下のバリアントのいくつかを使用してください。

制御されたワイルドカード配置でLIKEを実行するには:

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

使用する:

SELECT * FROM fiberbox WHERE field REGEXP '^1740 |1938 $|1940 (.*) test';
  • 値の前に^を置くと、行の始まりを示します。

  • 値の後に$を配置すると、行の終わりを示します。

  • (。*)の配置は、%ワイルドカードと同じように動作します。

  • 。改行を除く任意の1文字を示します。配置しています。inside()with *(。*)は、行末までの任意の数の文字を示す繰り返しパターンを追加します。

特定の一致を絞り込むためのより効率的な方法がありますが、そのためには正規表現をさらに確認する必要があります。注:すべての正規表現パターンがMySQLステートメントで機能するとは限りません。パターンをテストして、何が機能するかを確認する必要があります。

最後に、複数のLIKEフィルタとNOT LIKEフィルタを実行するには、次のようにします。

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

REGEXP代替を使用:

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

または混合代替:

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

NOTセットを別のWHEREフィルターで分離したことに注意してください。否定パターン、前向きパターンなどを使用して実験しました。ただし、これらの式では、望ましい結果が得られなかったようです。上記の最初の例では、^ 9999 $を使用して完全一致を示しています。これにより、同じ式でワイルドカードを使用して特定の一致を追加できます。ただし、リストされている2番目の例でわかるように、これらのタイプのステートメントを混在させることもできます。

パフォーマンスについては、既存のテーブルに対していくつかのマイナーテストを実行しましたが、バリエーション間で違いはありませんでした。ただし、データベースが大きくなる、フィールドが大きくなる、レコード数が増える、フィルタが複雑になると、パフォーマンスが問題になる可能性があると思います。

いつものように、理にかなうように上記のロジックを使用してください。

正規表現について詳しく知りたい場合は、www.regular-expressions.infoを参照サイトとしてお勧めします。


値がNULLのフィールドはREGEXPと一致しないことに注意してください。IFNULLを使用してこの問題を解決できます。WHERE IFNULL(field, '') NOT REGEXP '1740 | 1938'

@DanyMarcoux(。*)を使用したいのですが、FIELDNAME LIKE '%%'のように機能する必要があります。これを正規表現で使用する方法により、空の文字列が渡されます。それは...すべてのレコードをフェッチする必要があります
shzyincu

WHEREフィールドNOT LIKE '%1940%'またはフィールドNOT LIKE 'test%'は常にすべての行を返します。それはおそらく、あなたが述べた望ましい結果が得られない一因となったのでしょうか?
Herbert Van-Vliet

14

インラインビューまたは一時テーブルを作成し、値を入力してこれを発行できます。

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

ただし、これfiberboxはのようなに対して複数の行を返す可能性がある'1740, 1938'ため、このクエリはより適切に適合します。

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
        )

13

値のリストを使用した正規表現の方法

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

7

申し訳ありませんが、LIKE INmysqlのような操作はありません。

結合なしでLIKE演算子を使用する場合は、次のようにする必要があります。

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

MySQLはそのクエリを最適化しません、FYI。


4

REGEXPで「LIKE IN」機能を使用しようとしている人に注意してください。

INでは次のことができます。

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

REGEXPではこれは機能しません

REGEXP '
val1$|
val2$|
val3$
'

次のように1行にする必要があります。

REGEXP 'val1$|val2$|val3$'

3

オペランドを反転

'a,b,c' like '%'||field||'%'

2
あなたがいくつかのフィールドを明示的に持っているときは何かに等しいでしょう。卒業生'a'、 'b'、 'c'の enum はab、ac、bcで create table x(en enum('a,b,c')));insert into x values('a'),('b')はありませんenはaまたはbのみです。この方法を使用して、オペランドselect * from, x where 'a,c' like concat('%',en,'%')を反転することで、SQL接合でより安全になり、$ ^などの

これは同等ではなく、一般的なケースでは機能しません。あなたは知っていたならば、それはfield唯一正確にすることができabまたはcあなたが使用する必要がありますfield IN ('a', 'b', 'c')。しかし、一般的なケースでは、field LIKE '%a%' OR field LIKE '%b%' OR ...フィールド自体がtrueになるが式がfalseになるようなmagicものになる可能性があるため、これを置き換えることはできません。'magic' LIKE '%a%''a,b,c' LIKE '%magic%'
ADTC、2017年

2

これは正しいでしょう:

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

2

ほんの少しのヒント:

自然言語のように聞こえ、短くなるので、バリエーションRLIKEREGEXPとまったく同じコマンド)を使用することを好みます。まあ、ちょうど1文字。

「R」プレフィックスはRegです。もちろん。


0

あなたは正規表現の助けを借りて所望の結果を得ることができます。

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

上記のクエリをテストできますSQLフィドルをクリックしてください

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

上記のクエリをテストできますSQLフィドルをクリックしてください


1
これは正しくない正規表現です。[...]文字セットです。これは、セット内の任意の文字が一致と見なされるのに十分であることを意味します。だから、任意の値の数字とは" 0134789または|パイプ文字がこれを一致します。
Martijn Pieters
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.