Почему этот запрос SELECT не возвращает ожидаемых результатов? - PullRequest
1 голос
/ 31 июля 2011

Мне нужна помощь с запросом на выбор, но прежде чем задать вопрос, я дам краткое описание того, как работает моя система:

Моя база данных имеет отношение многие ко многим:

table product:
prd_cod(pk) //stores the product code ex: 0,1,2
cat_cod(fk) 
prd_name    //stores the product name, ex: tv, gps, notebook

table description_characteristc:
prd_cod(fk) 
id_characteristic(fk)
description //stores the description of the characteristic, ex: sony, 1kg, hj10

table characteristic:
id_characteristic (pk)
name_characteristic //store the name of characteristic, ex: brand, weight, model

Я уже сделал предложение jQuery (в index.php), где каждое набираемое мной слово вызывает offer.php, которое делает выбор и возвращает результат в поле предложения в индексе:

<?php



header('Content-type: text/html; charset=UTF-8');


$hostname = 'localhost';

$username = 'root';

$password = '';

$dbname = 'cpd';



mysql_connect($hostname, $username, $password)or die('Erro ao tentar conecta o banco 
de dados.');


mysql_select_db( $dbname );



if( isset( $_REQUEST['query'] ) && $_REQUEST['query'] != "" )

{
$q = mysql_real_escape_string( $_REQUEST['query'] );



if( isset( $_REQUEST['identifier'] ) && $_REQUEST['identifier'] == "sugestao")

{
$sql = "SELECT p.prd_name, d.description

FROM product p

INNER JOIN description_characteristc d using (prd_cod)

WHERE '".$q."' like concat(p.prd_name, '%') AND

concat(p.prd_name, ' ', d.description) like concat('".$q."', '%')LIMIT 10";



$r = mysql_query( $sql );


if ( $r )
{

echo '<ul>'."\n";

$cont = 0;

while( $l = mysql_fetch_array( $r ) ){

    $p = $l['nome'];

    $p = preg_replace('/(' . $q . ')/i', '<span style="font-
                     weight:bold;">$1</span>',  

$l['prd_nome'].'&nbsp;'.$l['descricao'].'&nbsp;'.$l['descricao']);

echo "\t".'<li id="autocomplete_'.$cont.'"              
  rel="'.$l['prd_nome'].'.'.$l['descricao'].'">'. utf8_encode( $p ) .'</li>'."\n";
$cont++;
}

echo '</ul>';


}
}


}



?>

Вот мои вопросы:

  1. В настоящее время, когда пользователь вводит 't', выборка ничего не приносит, только когда пользовательский тип 'tv' приносит результат:

    tv led tv plasm tv samsumg

    Мне бы хотелось, чтобы, когда пользователь набрал 't', селект принес мне 'tv'.

  2. Когда вы набираете 'TV Plasm', дважды появляется одно и то же имя_характера:

    ex: tv plasm plasm

  3. В настоящее время мой выбор выбирает имя_принца и описания таблицы description_characteristc:

    tv led

    Я бы хотел, чтобы мой выбор мог сделать и обратный выбор, например: led tv.

  4. Мне бы хотелось, чтобы при отображении результатов выбора могла быть функция кэширования, показывающая порядок поиска наиболее популярных для поиска менее; помня, что prd_name хранит только 'tv'.

Помощь, которую я ищу, может быть в форме выбора, как в форме процедуры. Также я могу редактировать php файл.

Ответы [ 2 ]

1 голос
/ 01 августа 2011

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

<?php

  $words = preg_split("/[^\\w]+/", $q);
  $first = $words[0] + "%";
  $all = implode(" ", $words) + "%";

?>

, а затем использовать переменные $first и $all в этом запросе:

SELECT  p.prd_name, d.description
FROM    product p
JOIN    description d
ON      d.prd_cod = p.prd_cod
WHERE   p.prd_name LIKE '$first'
        AND CONCAT(p.prd_name, ' ', d.description) LIKE '$all'

Создайте индекс для product (prd_name), чтобы он работал быстро.

Если вы хотите, чтобы слова соответствовали в любом порядке, вам нужно будет создать индекс FULLTEXT для ваших таблиц (это возможно только вMyISAM):

CREATE FULLTEXT INDEX fx_product_name ON product (prd_name)
CREATE FULLTEXT INDEX fx_description_name ON description (description)

и напишите запрос следующим образом:

SELECT  p.prd_name, d.description
FROM    (
        SELECT  prd_cod
        FROM    product pi
        WHERE   MATCH(prd_name) AGAINST ('lcd tv' IN BOOLEAN MODE)
        UNION
        SELECT  prd_cod
        FROM    description di
        WHERE   MATCH(description) AGAINST ('lcd tv' IN BOOLEAN MODE)
        ) q
JOIN    product p
ON      p.prd_cod = q.prd_cod
JOIN    description d
ON      d.prd_cod= p.prd_cod
WHERE   MATCH(p.prd_name, d.description) AGAINST ('+lcd +tv' IN BOOLEAN MODE)

Обратите внимание на изменение синтаксиса поискового термина: 'lcd tv' во внутреннем запросе и '+lcd +tv' ввнешний.

Вы также можете установить @@ft_min_word_len в 1 для более коротких слов, таких как tv или gps, для соответствия.

Так как MySQL не может построитьполнотекстовый индекс из двух или более таблиц одновременно, было бы проще, если бы вы денормализовали свои таблицы и поместили prd_name в таблицу description.Таким образом, вы можете избавиться от объединений и просто написать:

SELECT  prd_name, description
FROM    description d
WHERE   MATCH(prd_name, description) AGAINST ('+lcd +tv' IN BOOLEAN MODE)
1 голос
/ 01 августа 2011

Вы неправильно используете предложение LIKE и, похоже, не знаете, что означает "И". Важно отделить «и», как используется в обычной речи, от «И», как и в программировании. И в программировании означает «ОБА ДОЛЖЕН БЫТЬ ИСТИННЫМ». «и» в обычной речи может означать «одно из этих состояний, вы понимаете, что я имею в виду?»

Кроме того, вы не должны собирать SQL, как это, это случайность, которая должна произойти. Вы действительно должны найти способ связать переменные в операторах SQL. Я не знаю PHP, поэтому ничего не могу с этим поделать.

Во-первых, вы должны использовать это в предложении WHERE p.prd_name LIKE '$q%'. Попробуйте это вне PHP - вне Интернета - просто как простой запрос SQL: SELECT * FROM PRODUCT P WHERE P.PRD_NAME LIKE 'T%'.

Во-вторых, вы должны исправить «И» на «ИЛИ», поскольку вы хотите, чтобы одно условие ИЛИ другое условие было истинным. Если вы хотите, чтобы ОБА условия выполнялись, вряд ли что-то совпадет.

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