Я хотел бы найти в моей таблице столбец с именами и столбцом имен. В настоящее время я принимаю поисковый запрос из поля и сравниваю его с обоими столбцами, по одному за раз с
select * from table where first_name like '%$search_term%' or last_name like '%$search_term%';
Это отлично работает с условиями поиска по одному слову, но в набор результатов входят все с именем «Ларри». Но если кто-то вводит имя, то пробел, затем фамилию, я хочу более узкий результат поиска. Я пробовал следующее без успеха.
select * from table where first_name like '%$search_term%' or last_name like '%$search_term%' or concat_ws(' ',first_name,last_name) like '%$search_term%';
Любой совет?
EDIT: Название, с которым я тестирую, – «Ларри Смит». ДБ хранит «Ларри» в столбце «first_name» и «Smith» в столбце «last_name». Данные чистые, без лишних пробелов, а поисковый запрос обрезается влево и вправо.
EDIT 2: Я пробовал ответить Роберту Гэмбл сегодня утром. Его очень похоже на то, что я бежал прошлой ночью. Я не могу это объяснить, но сегодня утром это работает. Единственное различие, о котором я могу думать, это то, что вчера вечером я запустил функцию concat как третий «или» сегмент моего поискового запроса (после просмотра first_name и last_name). Сегодня утром я провел его как последний сегмент, просмотрев выше, а также адреса и названия компаний.
Работает ли функция mysql в конце запроса лучше, чем в середине?
То, что вы должны работать, но может быть уменьшено до:
select * from table where concat_ws(' ',first_name,last_name) like '%$search_term%';
Можете ли вы предоставить пример имени и условия поиска, когда это не работает?
Обратите внимание, что поисковый запрос теперь чувствителен к регистру.
Когда используешь
SELECT * FROM table WHERE `first_name` LIKE '%$search_term%'
Он будет соответствовать как «Ларри», так и «Ларри». С этим concat_ws он внезапно станет чувствительным к регистру!
Это можно исправить, используя следующий запрос:
SELECT * FROM table WHERE UPPER(CONCAT_WS(' ', `first_name`, `last_name`) LIKE UPPER('%$search_term%')
Изменить: Обратите внимание, что это работает только с не двоичными элементами. См. Также ответ mynameispaulie .
Люку:
Я согласен с вашим ответом, хотя хотел бы добавить, что UPPER работает только с недвоичными элементами. Если вы работаете со сканированием столбца AGE (или любого числа), вам необходимо выполнить преобразование CAST, чтобы функция UPPER работала правильно.
SELECT * FROM table WHERE UPPER(CONCAT_WS(' ', first_name, last_name, CAST(age AS CHAR)) LIKE UPPER('%$search_term%');
Простите меня за то, что я не отвечал на ответ Люка напрямую, но для жизни я не мог понять, как это сделать. Если администратор может переместить мой пост, сделайте это.
SELECT *,concat_ws(' ',first_name,last_name) AS whole_name FROM users HAVING whole_name LIKE '%$search_term%'
… возможно, то, что вы хотите.
Есть несколько вещей, которые могут мешать – ваши данные чисты?
Может быть, у вас есть пробелы в конце поля первого имени, что означает, что у вас есть два пробела между первым и последним, когда вы их объединяете? Использование trim (first_name) / trim (last_name) исправит это, хотя реальное исправление заключается в обновлении ваших данных.
Вы также можете это сопоставить, где встречаются два слова, но не обязательно вместе (предполагая, что вы находитесь в php, который предлагает вам переменная $ search_term)
$whereclauses=array(); $terms = explode(' ', $search_term); foreach ($terms as $term) { $term = mysql_real_escape_string($term); $whereclauses[] = "CONCAT(first_name, ' ', last_name) LIKE '%$term%'"; } $sql = "select * from table where"; $sql .= implode(' and ', $whereclauses);
вы можете сделать это (работа в mysql), вероятно, другой SQL тоже .. просто попробуйте это:
select * from table where concat(' ',first_name,last_name) like '%$search_term%';
Вы можете попробовать следующее:
select * FROM table where (concat(first_name, ' ', last_name)) = $search_term;