2012-09-26 27 views
0

在我的腳本中,如果行與用戶輸入的行相似,則用戶輸入表單並從MYSQL表中返回行。我正在建立一個搜索引擎,一切都基於等級。但我希望能夠調整下面的代碼,以查看「iPad」這個單詞有多少次與行字段相關,即「標題」,「描述」,「關鍵字」和「鏈接」。如果是這樣,我希望該行返回的高於說具有更高ID的行,但只在所有字段中提及iPad一次。 我的代碼如下: 條款一起查詢: $查詢=「選擇*從掃描WHERE」;如何在MySQL中掃描我的所有字段以進行表單輸入

$terms = array_map('mysql_real_escape_string', $terms); 
$i = 0; 
foreach ($terms as $each) { 
     if ($i++ !== 0){ 
      $query .= " AND "; 
     } 
     $query .= "title LIKE '%{$each}%' OR link LIKE '%{$each}%' OR keywords LIKE '%{$each}%' OR description LIKE '%{$each}%' "; 

} 

    $query = mysql_query($query) or die('MySQL Query Error: ' . mysql_error($connect)); 

echo '<p class="time">Qlick showed your results in ' . number_format($secs,2) . ' seconds.</p>';  

$numrows = mysql_num_rows($query); 
if ($numrows > 0) { 

     while ($row = mysql_fetch_assoc($query)) { 
      $id = $row['id']; 
      $title = $row['title']; 
      $description = $row['description']; 
      $keywords = $row['keywords']; 
      $link = $row['link']; 
      $rank = $row['rank']; 


    Seperate Terms Query 

      $query = " SELECT * FROM scan WHERE "; 

    $terms = array_map('mysql_real_escape_string', $terms); 
    $i = 0; 
    foreach ($terms as $each) { 
      if ($i++ !== 0){ 
       $query .= " OR "; 
      } 
      $query .= "title LIKE '%{$each}%' OR link LIKE '%{$each}%' OR keywords LIKE '%{$each}%' OR description LIKE '%{$each}%' "; 
     } 

    // Don't append the ORDER BY until after the loop 

      $query = mysql_query($query) or die('MySQL Query Error: ' . mysql_error($connect)); 
    $numrows = mysql_num_rows($query); 
    if ($numrows > 0) { 

      while ($row = mysql_fetch_assoc($query)) { 
       $id = $row['id']; 
       $title = $row['title']; 
       $description = $row['description']; 
       $keywords = $row['keywords']; 
       $link = $row['link']; 
       $rank = $row['rank']; 
+0

你嵌套的MySQL查詢,這是不是一個好主意。它可能適用於一個小數據集,但是一旦你經過了幾百行,它就結束了。 – Josh

回答

0

我會嘗試使用這種在其上運行一個查詢FULLTEXT輔助領域,在其中你會保存所有文本數據做:

http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html 

另一種方法是運行濾波MySQL和PHP中的排名。您可以通過在拼接字段上運行單個LIKE來擠壓某些性能。

順便說一句,您的代碼在LIKE中缺少圓括號,因此結果將不正確:您不得要求WHERE field1 LIKE 'x' OR field2 LIKE 'x' AND field1 LIKE 'y' OR...,您必須說明WHERE (field1 LIKE 'x' OR field2 LIKE 'x') AND (field1 LIKE 'y' OR...)

// Here we search for ALL terms (all must be present at least once) 
// use ' OR ' to ask that at least one term must be present once. 
$where = array(); 
foreach($terms as $term) 
    $where[] = "(CONCAT(title,'|',link,'|',keywords) LIKE '%{$term}%')"; 
$query .= ' WHERE ' . '('.implode(' AND ', $where).')'; 

現在你可以做的匹配項數的簡單排名OR情況下(與和數量總是項的總數):

$select_fields[] '(' . implode ('+', $where) . ') AS ranking'; 
在SQL你會

否則需要求助於真正醜陋的黑客:

(LENGTH(
    REPLACE(CONCAT(title,'|',link,'|',keywords),'{$term}','') 
) - LENGTH(CONCAT(title,'|',link,'|',keywords)))/LENGTH('{$term}'); 

這上面計算的文本,其中變奏的總長度之間的差異h將被完成並且相同文本的總長度爲,搜索字符串被刪除。這種差異當然與搜索字符串的存在次數成正比:如果字符串長度爲8個字符,則差異爲32意味着它存在四次。將長度差異除以該術語的長度,即可得到命中數。

的問題是幾個方面,你必須查詢極大地複雜化,這可能是真的很貴運行:

$select_fields = array('*'); 

$where = array(); 
$rank = array(); 
foreach($terms as $term) 
{ 
    // assume $term is NOT QUOTED 
    $search = mysql_real_escape_string($term); 
    $concat = "CONCAT(title,'|',link,'|',keywords)"; 

    $where[] = "(${concat} LIKE '%{$search}%')"; 
    $rank[] = "(LENGTH(REPLACE(${concat},'{$search}','')) 
      - LENGTH(${concat}))/LENGTH('{$search}')"; 
} 
$select_fields[] = "(".implode(",", $rank).") AS ranking"; 

$query .= "SELECT " . implode(',', $select_fields) 
     . ' FROM scan WHERE (' . implode(' AND ', $where) . ')'; 
相關問題