MySQL Search Query для двух разных полей - PullRequest
5 голосов
/ 18 марта 2010

Мне нужно искать по двум полям, используя функцию LIKE, и они должны совпадать в обратном порядке. Моя таблица использует InnoDB, у которого нет полнотекстового поиска.

Рассмотрим следующий случай:

У меня есть таблица пользователей со столбцами first_name и last_name. На нем есть строка со следующим значением:

{
    first_name: 'Ludwig',
    last_name: 'van Beethoven',
}

Случаи:

  1. Можно искать "Людвиг ван Бетховен"
  2. Можно искать "Бетховен Людвиг"
  3. Можно искать "Людвиг"
  4. Можно искать "Бетховен"

Я попробовал этот оператор SQL, но не повезло.

SELECT CONCAT(first_name, ' ', last_name) as fullname 
  FROM users 
 WHERE fullname LIKE '%Ludwig van Beethoven%';

Ответы [ 4 ]

7 голосов
/ 18 марта 2010

Вам необходимо переформулировать выражение concat в предложении where.

 SELECT CONCAT(first_name, ' ', last_name) as fullname 
      FROM users 
     WHERE CONCAT(first_name, ' ', last_name) LIKE '%doe%';

К сожалению "as" просто создайте псевдоним столбца, а не переменную, которую вы можете использовать в другом месте.

6 голосов
/ 18 марта 2010

Главное

Убедитесь, что у вас есть составной индекс на first_name и last_name. В противном случае действительно просто завершить полное сканирование таблицы независимо от того, как вы к этому подходите. Поэтому, если у вас его еще нет, создайте его:

CREATE INDEX users_firstandlast ON users(first_name, last_name);

Параметры синтаксиса

Как только этот индекс будет создан, у вас есть несколько вариантов:

Вариант 1 : Как сказал Уиллис Блэкберн , повторите CONCAT в своем предложении WHERE (поскольку AS не создает имя, которое вы можете использовать в WHERE пункт):

SELECT CONCAT(first_name, ' ', last_name) as fullname 
FROM users 
WHERE CONCAT(first_name, ' ', last_name) LIKE '%doe%';

Используйте EXPLAIN для проверки вашей конкретной ситуации, но в моих тестах говорится, что он использует составной индекс, даже если вы используете функцию в предложении WHERE.

Вариант 2 : В этом конкретном случае вы всегда можете просто использовать два LIKE в вашем WHERE предложении:

SELECT CONCAT(first_name, ' ', last_name) as fullname 
FROM users 
WHERE first_name LIKE '%doe%' or last_name LIKE '%doe%';

Опять же, это может использовать составной индекс (тогда как он не будет использовать отдельные индексы для столбцов first_name и last_name - это было бы, если бы вы не указывали с подстановочным знаком, но в соответствии с EXPLAIN [и ваш пробег может меняться, всегда проверяйте], в этом случае он идет со сканированием таблицы).

Вариант 3 В его ответ , Энди говорит, что вы можете использовать HAVING для этого. Мое прочтение руководства по MySQL предполагает, что оно сначала создаст набор результатов, и только затем применяет HAVING в самом конце, прежде чем отправлять его клиенту, и поэтому я бы остерегался этого. Но , в моих быстрых и грязных тестах, EXPLAIN говорит мне, что если у вас есть составной индекс, о котором я упоминал выше, версия HAVING выполняет поиск по индексу, а не сканирование таблицы. Если ваши тесты на реальных данных подтверждают это, это может быть хорошим вариантом для вас. Такое использование HAVING таким образом является расширением MySQL (не стандартным), но, опять же, так же, как и CONCAT, так что мы уже разбираемся с MySQL. :-) Но опять же, перепроверьте в своей реальной среде.

Заключение

Создайте индекс, если у вас его еще нет, тогда я бы выбрал вариант 2, если это возможно удаленно; в противном случае, вариант 1, если вы не можете найти (или Энди может предоставить) ссылку на вещь HAVING, не создающую массивный промежуточный набор результатов (это было бы действительно здорово, если бы было нестандартно, если бы этого не было). В любом случае, проверьте с помощью EXPLAIN и протестируйте в вашей конкретной среде.

2 голосов
/ 29 октября 2011

ВЫБРАТЬ * У пользователей, ГДЕ КОНКАТ (first_name, '', last_name) LIKE '% Ludwig%' ИЛИ ​​CONCAT (last_name, '', first_name) LIKE '% Ludwig%';

Все поисковые запросы, включая «Бетховен Людвиг».

0 голосов
/ 18 марта 2010

Когда вы CONCAT () двух столбцов, LIKE становится чувствительным к регистру. Так что это должно найти ваши результаты, но не является оптимальным для производительности:

SELECT CONCAT(first_name, ' ', last_name) AS fullname FROM users 
WHERE LOWER(CONCAT(first_name, ' ', last_name)) LIKE LOWER('%doe%');

Это заставляет MySQL работать над каждой строкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...