Главное
Убедитесь, что у вас есть составной индекс на 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
и протестируйте в вашей конкретной среде.