MySQL, как в ()?

204

Мой текущий запрос выглядит так:

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")
  • 0
    FIND_IN_SET не принимает подстановочные знаки, такие как %
Теги:

10 ответов

336
Лучший ответ

A REGEXP может быть более эффективным, но вам нужно будет проверить его, например,

SELECT * from fiberbox where field REGEXP '1740|1938|1940'; 
  • 2
    Мне нравится этот ответ - быстро, просто, я получил все «опции» в одну строку, как я хотел (легко редактировать). На небольшой набор результатов я нацеливаюсь, никакого снижения производительности вообще.
  • 4
    Кто-нибудь тестировал это на больших наборах данных?
Показать ещё 7 комментариев
141

Ответ Пол Диксон блестяще работал у меня. Чтобы добавить к этому, вот некоторые вещи, которые я наблюдал для тех, кто заинтересован в использовании 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';
  • Размещение ^ перед значением означает начало строки.

  • Размещение $после того, как значение указывает конец строки.

  • Размещение (. *) ведет себя подобно шаблону%.

  • . указывает любой символ, кроме разрывов строк. Размещение. 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 как хороший ссылочный сайт.

  • 2
    Круто, офигенно, офигенно. Отличная работа.
  • 2
    +1 очень всесторонне, спасибо!
Показать ещё 5 комментариев
13

Вы можете создать встроенный просмотр или временную таблицу, заполнить ее значениями и выдать следующее:

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
        )
  • 2
    +1, никогда не понимал заявления JOIN до сих пор.
8

Регулярный путь со списком значений

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

К сожалению, в mysql нет операции, аналогичной LIKE IN.

Если вы хотите использовать LIKE-оператор без соединения, вам придется сделать это следующим образом:

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

Вы знаете, MySQL не будет оптимизировать этот запрос, FYI.

3

Флип-операнды

'a,b,c' like '%'||field||'%'
  • 0
    Можете ли вы объяснить, как это будет работать немного больше, пожалуйста?
  • 2
    когда у вас есть какое-то поле явно будет равно что-то, например. Перечисление для классов 'a', 'b', 'c', но не ab, ac или bc, create table x(en enum('a,b,c')));insert into x values('a'),('b') en только a или b выполняет этот метод, переключая oprands select * from, x where 'a,c' like concat('%',en,'%') может быть безопаснее в SQL Injunction, нет необходимости избегать символов, таких как $ ^ и т. д.
Показать ещё 1 комментарий
2

Просто отметьте, кто хочет, чтобы REGEXP использовал функциональность "LIKE IN".

IN позволяет:

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

В REGEXP это не сработает

REGEXP '
val1$|
val2$|
val3$
'

Он должен быть в одной строке следующим образом:

REGEXP 'val1$|val2$|val3$'
1

Вы можете получить желаемый результат с помощью Регулярные выражения.

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 или | символ трубы будет соответствовать этому.
1

Просто немного подсказки:

Я предпочитаю использовать вариант RLIKE (точно такая же команда, как REGEXP), поскольку он больше похож на естественный язык и короче; ну, всего 1 char.

Префикс "R" для Reg. Разумеется, конечно.

1

Это будет правильно:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню