2014-09-25 125 views
2

我正在處理內部搜索引擎(MySQL數據庫)的SQL請求。我想讓用戶搜索精確的表達式,因此當他們搜索"foo bar"時,他們將獲得包含foobar的文檔,而不僅僅是foobar如何選擇具有相同ID的行共享一組值?

search_documents_words表:

| word_id | doc_id | word | 
--------------------------- 
| 1  | 1  | foo | 
| 2  | 1  | bar | 
| 3  | 2  | foo | 

search_documents表:

| doc_id | doc_name | 
--------------------- 
| 1  | mydoc1 | 
| 2  | mydoc2 | 

我想什麼:

| doc_id | doc_name | 
-------------------- 
| 1  | mydoc1 | 

假設我有我的關鍵字在一個PHP數組。

我該如何做到這一點?

+0

那麼到目前爲止,我只是有一個查詢使用'IN'函數 - 這是工作很好,但只適用於「常規搜索」:'SELECT sdoc_id,sdoc_document,sdoc_type FROM search_documents_words,search_documents WHERE sdoc_id = swd_doc AND swd_word IN( 「。)join(',',$ _ words)。」)GROUP BY sdoc_id' – vard 2014-09-25 12:45:29

回答

1

假設你的搜索關鍵字在陣列

$search = array('foo','bar'); 
$keywords = ''; 
foreach($search as $values) { 
    $keywords .= "'.$values.',"; 
} 
$keywords = rtrim($keywords,","); // creating words as 'foo','bar' 

然後執行此查詢

$query = "SELECT B.* 
      FROM search_documents_words A 
      JOIN search_documents B ON A.doc_id = B.doc_id 
      WHERE A.word IN(".$keywords.")"; 

EDITED

如果同一個文件編號不重複的字此情況下將工作(具有許多foo條目的doc 1將不適用於此查詢)

$query = "SELECT B.* 
      FROM search_documents_words A 
      JOIN search_documents B ON A.doc_id = B.doc_id 
      WHERE A.word IN(".$keywords.") 
      GROUP BY A.doc_id HAVING COUNT(A.doc_id) = '".count($search)."' "; 
+0

沒有安裝MySQL,但我認爲你在查詢之前需要一個DISTINCT B. * – Sparky 2014-09-25 10:28:25

+0

如果我是正確的,這個查詢只會看爲'foo'或'bar',而不是'foo'和'bar'。這與我用於常規搜索的內容非常相似。 – vard 2014-09-25 12:35:11

+0

查詢將看起來像WHERE A.word IN('foo','bar');它會尋找foo和bar。先嚐試一下。 – Shafeeque 2014-09-25 12:47:20

0

您可以使用GROUP_CONCAT和HAVING子句

SELECT sd.doc_id, 
      sd.doc_name, 
GROUP_CONCAT(sdw.word  Order by sdw.word SEPARATOR ' ') AS sdwWord 
    FROM search_documents sd 
    JOIN search_documents_words sdw ON sd.doc_id = sdw.doc_id 
    GROUP BY sd.doc_id, sd.doc_name 
    HAVING sdwWord = <search expression> 
+0

如果關鍵字的順序與它們在數據庫中的順序不同,那麼如何管理此查詢?因爲如果'GROUP_CONCAT'返回'bar foo','HAVING'不會接受'foo bar'。除非有一個我不知道的功能,我可以使用它。 – vard 2014-09-25 12:37:40

+0

@vard,好點,添加順序,它只適用於foo bar位不適用於bar foo,如果您希望bar foo也匹配,則該組合需要添加到search_documents_words表中 – radar 2014-09-25 12:42:15

1

子查詢可以建立這樣的:

$keywords = array('foo','bar'); 
foreach($keywords as $key) 
{ 
    $conditions[] = "word='".$key."'"; 
} 
$condition = implode(" AND ",$conditions); 

然後執行此SQL查詢:

$query = "SELECT * 
      FROM search_documents 
      WHERE doc_id 
      IN (SELECT doc_id 
       FROM search_documents_words 
       WHERE ".$condition.")" 

希望這有助於!

+0

看起來像正確答案我!我會確認服務器一回來,我希望這不是這個讓他崩潰的查詢(我有大約30k的關鍵字和大約5k的文檔)。對於記錄,這裏是查詢我結束了:'SELECT sdoc_id,sdoc_document FROM search_documents_words,search_documents WHERE sdoc_id = swd_doc AND sdoc_id IN(SELECT sdoc_id FROM search_documents_words WHERE「。implode('AND',$ conditions)。」)GROUP BY sdoc_id' – vard 2014-09-25 12:42:45

相關問題