2013-05-15 4 views
0

Я работаю на сайте, который позволяет пользователям перечислить лодки и яхты для продажи. Существует база данных mysql с таблицей «Яхты», а среди других полей - «make» и «model».MySql Search Query for Two Combined Fields

Когда люди приходят на сайт, чтобы искать лодки для продажи, есть форма поиска, один из вариантов - ввести марку и/или модель в текстовое поле. Соответствующий пункт, где на странице результатов заключается в следующем

WHERE (make LIKE '%$yacht_make%' OR model LIKE '%$yacht_make%') 

Это работает, если кто-то входит либо марку или модель, но не тогда, когда они входят в оба.

Например, если кто-то входит в «Jeanneau», марка, он находит лодку с этим маркером, или если они входят в «Sun Odyssey», модель, она находит лодку этой модели, но если они войдут в " Jeanneau Sun Odyssey "это пустая.

Есть ли способ написать запрос, где все три способа ввода вышеуказанных критериев поиска найдут лодку?

Вот сайт http://yachtsoffered.com/

Спасибо,

Роб Фенвик

Edit:

Запрос построен с PHP скрипт здесь это скрипт

if(!empty($yacht_id)) { 
    $where = " WHERE yacht_id = $yacht_id "; 
} else { 
    $where = " WHERE (make LIKE '%$yacht_make%' OR model LIKE '%$yacht_make%') "; 
    if(!empty($year_from) && !empty($year_to)){ 
     $where .= "AND (year BETWEEN $year_from AND $year_to) "; 
    } 
    if(!empty($length_from) && !empty($length_to)){ 
     $where .= "AND (length_ft BETWEEN $length_from AND $length_to) "; 
    } 
    if(!empty($price_from) && !empty($price_to)){ 
     $where .= "AND (price BETWEEN $price_from AND $price_to) "; 
    } 
    if ($sail_power != 2){ 
     $where .= "AND (sail_power = $sail_power) "; 
    } 
    if (count($material_arr) > 0){ 
     $material = 'AND ('; 
     foreach ($material_arr as $value) { 
      $material .= ' material LIKE \'%' . $value . '%\' OR'; 
     } 
     $material = substr_replace ($material , ') ' , -2); 
     $where .= $material; 
    } 
    if (count($engine_arr) > 0){ 
     $engine = 'AND ('; 
     foreach ($engine_arr as $value) { 
      $engine .= ' engine LIKE \'%' . $value . '%\' OR'; 
     } 
     $engine = substr_replace ($engine , ') ' , -2); 
     $where .= $engine; 
    } 
    if (count($type_arr) > 0){ 
     $type = 'AND ('; 
     foreach ($type_arr as $value) { 
      $type .= ' type LIKE \'' . $value . '\' OR'; 
     } 
     $type = substr_replace ($type , ') ' , -2); 
     $where .= $type; 
    } 
    if (count($region_arr) > 0){ 
     $region = 'AND ('; 
     foreach ($region_arr as $value) { 
      $region .= ' region LIKE \'' . $value . '\' OR'; 
     } 
     $region = substr_replace ($region , ') ' , -2); 
     $where .= $region; 
    }  
     $where .= 'AND (active = 1) ORDER BY yacht_id DESC'; 
} 

$sql = "SELECT * FROM $tbl_name $where LIMIT $start, $limit"; 
$result = mysql_query($sql); 
+0

Вы можете разместить весь свой запрос? –

+0

, когда оба введены в ваше поисковое поле в одном поле с маркой и моделью, поэтому он не работает, вам нужно либо явно разделить 2, использовать 2 входа, либо разделить текст на вход пользователя –

+0

Спасибо Дагон, да, я понимаю, почему это не так я думал о том, чтобы разобрать два поля ввода, но я хотел знать, есть ли еще один вариант, проблема с их выплеском - нет способа рассказать, какие слова являются маркой, которую модель, я полагаю, я мог бы искать каждый слово, но это принесло бы слишком много результатов. –

ответ

1

Есть много способов сделать это, самый простой на мой взгляд:

$search = preg_replace('/\s+/','|', $yacht_make); 
$sql = "select * from yacht where concat_ws(' ',make,model) rlike '$search'"; 

Это заменяет все пробелы с |, который используется в качестве OR в регулярном выражении подобный запросу при конкатенации всех полей поиска. Скорость его может быть сомнительной на тяжелых трафиковых сайтах, но довольно компактна и удобна для добавления дополнительных полей.

+0

Так легко сделать. RLIKE недостаточно используется в ответах на вопросы mysql. Также как concat_ws. Ссылки для людей: CONCAT_WS (http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_concat-ws) и RLIKE (http://dev.mysql.com/doc/refman /5.0/en/regexp.html#operator_regexp) – JClaspill

+0

Я получаю эту ошибку для строки preg_replace Ошибка синтаксиса: неожиданный '/', ожидающий ')' в C: \ xampp \ htdocs \ yachtsoffered \ results.php on line 70 –

+0

Извините за это, конечно, строка с регулярным выражением должна быть указана ... –

0

Ваша проблема в том, что в вашем запросе вы поиск точной подстроки «Jeanneau Sun Odyssey», которая не является ни маркой, ни моделью.

Самое простое решение - использовать отдельные поля ввода для марки и модели. Но если вам действительно нужно использовать один поле ввода, лучше всего было бы разделить на пространствах и добавить пункты для каждого отдельного слова, так что ваш запрос будет в конечном итоге выглядит что-то вроде

WHERE make like '%sun%' OR model like '%sun%' 
OR make like '%odyssey%' OR model like '%odyssey%' 
OR make like '%Jeanneau%' OR model like '%Jeanneau%' 
-1

После проверки вашего сайта кажется, что вы вводите только одно текстовое поле и ищете эту строку в каждом поле.

Итак, вы можете использовать полнотекстовый поиск (linkie), или вы можете разделить строку на пробелы и генерировать причину WHERE на лету. Вот грубый пример:

$searchterms = explode (' ', $input); 

$sql .= "... WHERE"; /* obviously need the rest of your query */ 


foreach ($searchterms as $term) { 
    if ((substr ($string, -5) != 'WHERE') && 
     (substr ($string, -3) == ' ||') { $sql .= " ||"; } 
    $sql .= " make LIKE '%$term%' || model LIKE '%$term%'"; 
} 
+0

только что заметил ошибку - исправит! –

+0

Здесь вам нужно [надлежащее SQL-экранирование] (http://bobby-tables.com/php). – tadman

0

Вы также можете использовать:

WHERE make LIKE '%$yacht_make%' 
    OR model LIKE '%$yacht_make%' 
    OR '$yacht_make' LIKE CONCAT('%', make, '%', model, '%') 
    OR '$yacht_make' LIKE CONCAT('%', model, '%', make, '%') 

Это не будет очень эффективным и до сих пор не поймать все возможности, например,если пользователь предоставит make и часть имени модели, например 'Jeanneau Odyssey' или в неправильном порядке: Sun Jeanneau Odyssey.

+0

Сколько раз я был в этом положении и не знаю, что вы могли бы это сделать! Я собираюсь поменять некоторые запросы сейчас, поэтому у меня есть это в моем коде - спасибо –

+0

@ Дагонные запросы с 'LIKE '% searchstring'' не эффективны. –

+0

Реверсированные аргументы в LIKE - прекрасная функция, но здесь было бы трудно найти что-то трудное - вам нужно было бы предоставить точный make и модель, необязательно отделенную, префиксную и за которой следует что-то несвязанное, но никаких результатов для запросов с использованием только модели или только модели или с частью каждого из них. Он нашел бы «123 Jeanneau 123 Sea Odyssey 213», но не «Jeanneau Odyssey» ' –

0

Спасибо всем, я в конечном итоге с помощью решения Dev-нуль-Dweller превыше

Я пересмотрел свой код как следующий,

, чтобы получить значение и избежать здесь код,

if (isset($_GET['yacht_make'])) { 
    $yacht_make = cleanString($_GET['yacht_make']); 
    $yacht_make = preg_replace('/\s+/','|', $yacht_make); 
} else { 
    $yacht_make = NULL; 
} 

И я пересмотрел первые несколько строк кода построения php-запроса, который я разместил выше, чтобы читать,

if(!empty($yacht_id)) { 
    $where = " WHERE yacht_id = $yacht_id "; 
} else { 

    $where = " WHERE (yacht_id LIKE '%')"; 

    if(!empty($yacht_make)){ 
     $where .= "AND (CONCAT_WS(' ',make,model) RLIKE '$yacht_make') "; 
    } 

Он работает красиво, хотя он приносит больше результатов, чем хотелось бы для «Jeanneau Sun Odyssey», поскольку он воспитывает «Bayliner Sunbridge», я предполагаю, потому что он соответствует «Солнцу».

Но это большое улучшение от того, что у меня было.

Спасибо Все

Роб Фенвик