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-журнал спільноти


1
WHERE FIND_IN_SET(f.fiberbox, "1740,1938,1940")
Джермунд Даль

2
FIND_IN_SET не приймає групові символи як%
Себастьян Grignoli

Відповіді:


453

REGEXP може бути більш ефективним, але ви повинні були б еталоном це , щоб бути впевненим, наприклад ,

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

2
Мені подобається ця відповідь - швидко, просто, я отримав усі "параметри" в одному рядку, як я хотів (легко редагувати). Що стосується невеликого набору результатів, на який я орієнтований, то зниження продуктивності зовсім не відбувається.
Майкл Уельс

51
Понад 1 мільйон рядків у моєму столі. REGEX навколо 0,0009 і LIKE навколо 0,0005. Якщо більше 5 REGEX, близько 0,0012 ...
Девід Белангер

10
У мене виникла проблема, яка REGEXPбула надмірно повільною, але мені потрібна гнучкість REGEXP, щоб звузити набір результатів далі, ніж LIKEміг забезпечити. Я придумав гібридне рішення, де я використовував і те, LIKEі REGEXP; незважаючи на те, що REGEXPчастина була достатньою для отримання правильних результатів, використовуючи LIKEдобре дозволений MySQL значно зменшити набір результатів перед тим, як використовувати повільніші REGEXPкритерії.
квітня 1212

1
Щоб отримати значення (select group_concat(myColumn separator '|') from..)
rgexp

5
Додавання до даних про ефективність. На MySql 5.5 у таблиці з 229М рядками 1 додаток залишив якірний 3 знаки пошуку: REGEXP: 16s, LIKE: 8.5s; 2 терміни: REGEXP: 22.1s, LIKE: 9.69; '^ (гемоглобін | гематр? окрит). *' проти 3 терміна, як: REGEXP: 36.3, LIKE: 9.59.
Джессі Кларк

181

Відповідь Пола Діксона блискуче спрацювала на мене. Щоб додати до цього, ось деякі речі, які я спостерігав для тих, хто зацікавлений у використанні REGEXP:

Щоб виконати кілька фільтрів LIKE за допомогою Wildcards:

 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 та між | (АБО) оператор трактується як макіяж. Зазвичай для 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';
  • Розміщення ^ перед значенням вказує на початок рядка.

  • Розміщення $ після значення вказує на кінець рядка.

  • Розміщення (. *) Виглядає так само, як і символи% wild.

  • The. позначає будь-який окремий символ, крім розривів рядків. Розміщення. inside () з * (. *) додає повторюваний шаблон із зазначенням будь-якої кількості символів до кінця рядка.

Є більш ефективні способи звуження конкретних збігів, але це потребує більшого перегляду регулярних виразів. ПРИМІТКА. Не всі схеми регулярних виразів працюють у операторах 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 $, щоб вказати точну відповідність. Це дає змогу додавати конкретні збіги з підстановочними відповідниками у тому ж самому виразі. Однак ви також можете змішувати ці типи операторів, як ви бачите у другому переліченому прикладі.

Щодо продуктивності, я провів деякі незначні тести на існуючій таблиці і не знайшов відмінностей між своїми варіаціями. Однак, я думаю, що продуктивність може бути проблемою з більшими базами даних, більшими полями, більшим числом записів та складнішими фільтрами.

Як завжди, використовуйте логіку вище, як це має сенс.

Якщо ви хочете дізнатися більше про регулярні вирази, я рекомендую www.regular-expressions.info як хороший довідковий сайт.


Майте на увазі, що поле зі значенням NULL не збігатиметься з REGEXP. Ви можете використовувати IFNULL для вирішення цієї проблеми. WHERE IFNULL(field, '') NOT REGEXP '1740 | 1938'

@DanyMarcoux Що робити, якщо я хочу використовувати (. *), Але він повинен діяти як FIELDNAME LIKE '%%', як його використовувати з regexp, так що коли буде передано порожній рядок. він повинен отримати всі записи ..
shzyincu

Поле WHERE НЕ ПОДОБАЄТЬСЯ '% 1940%' АБО НЕ СПОКОЄТЬСЯ 'test%' завжди повертає всі рядки. Це, можливо, сприяло тому, щоб не дати бажаних результатів, про які ви згадали?
Герберт Ван-Вліет

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
        )


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$
'

Він повинен бути в одному рядку, як це:

REGEXP 'val1$|val2$|val3$'

3

Операнди фліп

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

2
коли у вас є поле, явно щось би дорівнювало, наприклад, перерахунок для градів 'a', 'b', 'c', але не 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 Injunction, не потрібно бігти від таких заголовників, як $ ^ тощо.

Це НЕ еквівалентно і НЕ ПРАЦЮЄМО для загальних випадків. Якщо ви знали, що це fieldможе бути саме так a, bабо cтоді вам слід скористатися field IN ('a', 'b', 'c'). Але в загальних випадках це НІКОЛИ не може замінити, field LIKE '%a%' OR field LIKE '%b%' OR ...оскільки саме поле може бути чимось таким, magicщо могло б зробити 'magic' LIKE '%a%'істинним, але вираз 'a,b,c' LIKE '%magic%'хибним.
ADTC

2

Це було б правильно:

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

2

Лише невелика порада:

Я вважаю за краще використовувати варіант RLIKE (точно така ж команда, що і REGEXP ), оскільки це звучить більше як природна мова і коротший; ну, всього 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
Це неправильний регулярний вираз. [...]- це набір символів , що означає, що будь-якого з символів у наборі достатньо, щоб розглядатися як збіг. Таким чином , будь-яке значення з цифрами " 0, 1, 3, 4, 7, 8, 9або |характер труби слід пов'язати з цим.
Martijn Pieters
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.