MySQL GİBİ ()?


273

Mevcut sorgum şöyle:

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

Biraz etrafa baktım ve LIKE IN () benzeri bir şey bulamadım - bunun böyle çalışmasını öngörüyorum:

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

Herhangi bir fikir? Ben sadece problemi yanlış mı düşünüyordum - daha önce hiç görmediğim bazı belirsiz komutlar.

MySQL 5.0.77-topluluk günlüğü


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

2
FIND_IN_SET, joker karakterleri kabul etmiyor%
Sebastián Grignoli

Yanıtlar:


454

Bir REGEXP daha verimli olabilir , ancak emin olmak için karşılaştırmayı yapmanız gerekir, örn.

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

2
Bu cevabı beğendim - hızlı, basit, istediğim gibi bir satırda tüm "seçenekleri" aldım (kolay düzenleme). Hedeflediğim küçük sonuç kümesinde performansta hiç bir düşüş yok.
Michael Wales

51
Masamda 1 milyondan fazla satır. REGEX 0.0009 civarı ve GİB 0.0005 civarı. 5'ten fazla REGEX ise, 0,0012 civarı ...
David Bélanger

10
REGEXPÖnemsiz olarak yavaş olan bir sorunum vardı , ancak sonuç setimi LIKEsağlayabildiğinden daha daraltmak için REGEXP esnekliğine ihtiyacım vardı . İkisini de kullandığım karma bir çözüm buldum LIKEve REGEXP; REGEXPkısmın bana doğru sonuçları vermek için yeterli olmasına rağmen, LIKEdaha yavaş REGEXPkriterleri kullanmadan önce MySQL'in sonuç kümesini önemli ölçüde azaltmasına izin verdi .
mpen

1
Bir sütundan (select group_concat(myColumn separator '|') from..)
normal ifade

5
Performans verilerine ekleme. MySql 5.5'te 229M sıralı bir tabloda, 1 terim sol 3 karakterli arama demirli: REGEXP: 16s, LIKE: 8.5s; 2 terim: REGEXP: 22.1s, GİBİ: 9.69; '^ (hemoglobin | hematr? ocrit). *' vs 3 terim: REGEXP: 36.3, GİBİ: 9.59.
Jesse Clark

181

Paul Dixon'un cevabı benim için harika çalıştı. Buna eklemek için, REGEXP kullanmakla ilgilenenler için gözlemlediğim bazı şeyler:

Joker Karakterlerle birden çok LIKE filtresi gerçekleştirmek için:

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

REGEXP Alternatifini Kullan:

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

REGEXP tırnak içindeki ve | (VEYA) operatörü joker karakter olarak kabul edilir. Genellikle, REGEXP%.% 1740 olarak çalışmak için (. *) 1740 (. *) Gibi joker karakter ifadeleri gerektirir.

Joker karakterin yerleşimi üzerinde daha fazla denetime ihtiyacınız varsa, bu değişkenlerden bazılarını kullanın:

Kontrollü Joker Karakter Yerleşimi ile GİBİ Gerçekleştirmek İçin:

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

kullanın:

SELECT * FROM fiberbox WHERE field REGEXP '^1740 |1938 $|1940 (.*) test';
  • Değerin önüne ^ yerleştirilmesi satırın başlangıcını gösterir.

  • Değerin arkasına $ yerleştirmek satır sonunu gösterir.

  • (. *) Yerleştirme% joker karakterine çok benzer.

  • . satır sonları hariç herhangi bir karakteri belirtir. Yerleştirme. inside () ile * (. *), satır sonuna kadar istediğiniz sayıda karakteri gösteren yinelenen bir desen ekler.

Belirli eşleşmeleri daraltmanın daha etkili yolları vardır, ancak Düzenli İfadelerin daha fazla gözden geçirilmesini gerektirir. NOT: Tüm regex kalıpları MySQL deyimlerinde çalışmıyor gibi görünmektedir. Desenlerinizi test etmeniz ve neyin işe yaradığını görmeniz gerekir.

Son olarak, Birden Çok GİBİ ve GİBİ DEĞİL filtreleri gerçekleştirmek için:

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 Alternatifini Kullan:

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

VEYA Karışık Alternatif:

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

NOT setini ayrı bir WHERE filtresinde ayırdım. Negatif kalıpları, ileriye dönük kalıpları vb. Kullanmayı denedim. Bununla birlikte, bu ifadelerin istenen sonuçları verdiği görülmemiştir. Yukarıdaki ilk örnekte, tam eşleşmeyi belirtmek için ^ 9999 $ kullanıyorum. Bu, aynı ifadede joker karakter eşleşmeleriyle belirli eşleşmeler eklemenizi sağlar. Ancak, listelenen ikinci örnekte gördüğünüz gibi bu tür ifadeleri de karıştırabilirsiniz.

Performansla ilgili olarak, mevcut bir tabloya karşı bazı küçük testler yaptım ve varyasyonlarım arasında hiçbir fark bulamadım. Bununla birlikte, performansın daha büyük veritabanları, daha büyük alanlar, daha fazla kayıt sayısı ve daha karmaşık filtrelerle ilgili bir sorun olabileceğini düşünüyorum.

Her zaman olduğu gibi, yukarıdaki mantığı mantıklı olarak kullanın.

Düzenli ifadeler hakkında daha fazla bilgi edinmek istiyorsanız, iyi bir referans sitesi olarak www.regular-expressions.info adresini öneriyorum.


NULL değerine sahip bir alanın REGEXP ile eşleşmeyeceğini unutmayın. Bu sorunu çözmek için IFNULL kullanabilirsiniz. WHERE IFNULL(field, '') NOT REGEXP '1740 | 1938'

@DanyMarcoux Eğer (. *) Kullanmak istersem ama FIELDNAME LIKE '%%' gibi davranmalı, regexp ile nasıl kullanılmalı, böylece boş bir dize geçtiğinde. tüm kayıtları
getirmelidir

'% 1940%' GİBİ OLMAYAN ALANLAR VEYA 'test%' GİBİ OLMAYAN alanlar her zaman tüm satırları döndürür. Bu belki de bahsettiğiniz istenen sonuçları vermemeye katkıda bulunmuş olabilir?
Herbert Van-Vliet

14

Satır içi bir görünüm veya geçici bir tablo oluşturabilir, değerlerle doldurabilir ve bunu düzenleyebilirsiniz:

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

Ancak bu, fiberboxbunun gibi bir şey için birden çok satır döndürebilir '1740, 1938', böylece bu sorgu size daha iyi uyabilir:

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

Değerler listesiyle normal ifade yolu

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

7

Üzgünüz, LIKE INmysql ile benzer bir işlem yok .

LIKE operatörünü birleştirme olmadan kullanmak istiyorsanız, bunu şu şekilde yapmanız gerekir:

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

Biliyorsunuz, MySQL bu sorguyu FYI optimize etmeyecek.


4

Sadece "GİBİ" işlevini kullanmak için REGEXP çalıştıran herkese dikkat edin.

IN şunları yapmanızı sağlar:

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

REGEXP'de bu çalışmaz

REGEXP '
val1$|
val2$|
val3$
'

Bunun gibi bir satırda olması gerekir:

REGEXP 'val1$|val2$|val3$'

3

Flip işlenenler

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

2
bazı alanlarınız varsa açıkça bir şey eşit örneğin. mezunlar için bir enum , 'b', 'c' 'a' değil ab, ac veya bc create table x(en enum('a,b,c')));insert into x values('a'),('b') tr sadece a veya b oprands saygısız bu yöntemi yaparak select * from, x where 'a,c' like concat('%',en,'%')daha güvenli olabilir , SQL Buyruğunun gibi charactors kaçmaya gerek $ ^ vs.

Bu eşdeğer DEĞİLDİR ve genel durumlar için ÇALIŞMAYACAKTIR. fieldBunun tam olarak olabileceğini biliyorsan a, bya da ckullanmalısın field IN ('a', 'b', 'c'). Ancak genel durumlarda, bu ASLA değiştirilemez field LIKE '%a%' OR field LIKE '%b%' OR ...çünkü alanın kendisi doğru olan ancak ifade yanlış magicolan bir şey olabilir . 'magic' LIKE '%a%''a,b,c' LIKE '%magic%'
ADTC

2

Bu doğru olur:

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

2

Sadece küçük bir ipucu:

Ben varyant kullanmayı tercih RLIKE (tam olarak aynı komutu RegExp daha doğal dil gibi geliyor, ve daha kısa olduğu gibi); iyi, sadece 1 karakter.

"R" öneki Reg. Tabii ki Exp.


0

Düzenli İfadeler yardımıyla istediğiniz sonucu alabilirsiniz .

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

Yukarıdaki sorguyu test edebiliriz, lütfen SQL kemanına tıklayın

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

Yukarıdaki sorguyu test edebiliriz, lütfen SQL kemanına tıklayın


1
Bu yanlış bir normal ifadedir. [...]bir karakter kümesidir , yani kümedeki karakterlerden herhangi birinin eşleşme olarak görülmesi için yeterlidir. Yani herhangi bir değere hanesiyle ' 0, 1, 3, 4, 7, 8, 9veya |boru karakteri bu eşleşir.
Martijn Pieters
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.