为什么这个SELECT查询不会返回我期望的结果?

时间:2011-07-31 14:55:39

标签: mysql database select many-to-many

我在选择查询时需要帮助,但在提出问题之前,我将简要介绍一下我的系统是如何工作的:

我的数据库有多对多的关系:

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中),我输入的每个单词都调用suggest.php,它会生成一个select并将结果返回到索引中的建议框中:

<?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'时,选择为我带来'电视'。

  2. 当你输入'tv plasm'时,它会带来两次相同的name_character:

    ex: tv plasm plasm

  3. 目前我的select选择了prd_name和表description_characteristc的描述:

    tv led

    我希望我的选择也可以进行反向选择,例如:led tv

  4. 我希望在显示选择结果时,可能会有一个缓存功能,显示最少寻求的顺序;记住prd_name只存储'tv'。

  5. 我正在寻找的帮助可以采用select的形式,如过程的形式。另外,我可以编辑php文件。

2 个答案:

答案 0 :(得分:1)

您严重使用LIKE条款,而您似乎并不知道“AND”的含义。将“和”用于编程时使用的“和”中的“和”是很重要的。在编程中意味着“两者都必须是正确的”。 “和”在随意的演讲中可能意味着“其中一个条件,你知道我的意思吗?”

另外,你不应该像这样构建SQL,这是一个等待发生的事故。你真的应该找到一种方法将变量绑定到SQL语句中。我不懂PHP,所以我无法帮助。

首先,您应该在WHERE子句p.prd_name LIKE '$q%'中使用它。在PHP之外 - 在Web之外 - 尝试这个,就像一个简单的SQL查询:SELECT * FROM PRODUCT P WHERE P.PRD_NAME LIKE 'T%'

其次,你应该将“AND”修改为“OR”,因为你想要一个条件或其他条件为真。如果你想要两个条件都是真的,几乎没有任何东西可以匹配。

答案 1 :(得分:1)

您应该在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,以便匹配tvgps等较短的字词。

由于MySQL无法一次从两个或多个表构建全文索引,因此如果对表进行非规范化并将prd_name放入description表,则会更简单。这样,你可以摆脱连接,然后写:

SELECT  prd_name, description
FROM    description d
WHERE   MATCH(prd_name, description) AGAINST ('+lcd +tv' IN BOOLEAN MODE)