2011-09-17 82 views
-2

我有一個數據庫中的表像這樣 關鍵詞有效的搜索查詢

  • ID INT(11)
  • U_ID INT(11)
  • 關鍵字文本
  • CREATE_DATE INT的結構( 11)

U_ID爲外鍵,id是主鍵

關鍵字字段是用戶創建的用逗號分隔的單詞列表 我想知道是否有人可以建議有效的查詢來搜索這樣的表。

+2

切勿在數據庫中使用CSV。這是一個主要的罪惡! – Johan

回答

0

如果使用MyISAM,則可以在字段keywords上創建全文索引。然後搜索使用:

select * from keywords k where match('test') against(k.keywords); 

當然,在數據庫中的CSV只是你可以做的最糟糕的事情。你應該把關鍵字放在一個單獨的表格中。確保對所有表使用InnoDB。

Table tags 
------------- 
id integer auto_increment primary key 
keyword_id integer foreign key references keywords(id) 
keyword varchar(40) 

現在您可以選擇使用:

SELECT k.* FROM keywords k 
INNER JOIN tags t ON (t.keyword_id = k.id) 
WHERE t.keyword LIKE 'test' //case insensitive comparison. 

比CSV很多快得多。

+0

謝謝,我認爲這將簡化事情 – MrFoh

2

您應該更改數據庫設計,以便擁有一個名爲user_keyword的表並將每個關鍵字存儲在單獨的行中。然後,您可以索引此表並輕鬆地和有效地搜索它:

WHERE keyword = 'foo' 

如果不能修改數據庫那麼你可以使用FIND_IN_SET但它不會是非常有效:

WHERE FIND_IN_SET('foo', keywords) 
+0

如何更改數據庫設計 – MrFoh

+0

修改數據庫將意味着我將不得不使用前面的結構編寫代碼 – MrFoh

+0

WHERE FIND_IN_SET('foo',keywords)'就夠了,'!= 0'部分不是需要。 – Johan

-1

你有2種選擇:

  1. 重新structor數據庫,創建一個名爲關鍵詞額外的表,並應包括U_ID這將是映射到您的用戶表的外鍵,這樣你可以很容易地插入每個關鍵字輸入到關鍵詞表,然後搜索它使用的東西:

SELECT * FROM Keywords WHERE keyword LIKE %KEYWORD%

  1. 你可以得到關鍵字字段中,單獨的關鍵字,並使用您的首選語言把它們放到一個數組,然後搜索數組。
+2

錯誤的答案,在一個帶有「book,testing」的CSV列中,即使'test'本身不在該列中,這也會給出匹配。在SQL和php中混合查詢本身就是一種反模式。 – Johan

1

單獨的keywords在它自己的表中,通過FOREIGN KEY將它連接到舊錶,將它索引,並且您將能夠有效地搜索關鍵字前綴的確切關鍵字。

例如:

id U_id keywords create_date 
1 - A,B,C - 

變爲:

PARENT_TABLE: 
id U_id create_date 
1 - - 

CHILD_TABLE: 
id keyword 
1 A 
1 B 
1 C 

提供有上keyword索引,以下查詢應該是有效的:

SELECT * FROM PARENT_TABLE 
WHERE id IN (SELECT id FROM CHILD_TABLE WHERE keyword = ...) 

--- EDIT ---

根據Johan的下面的評論,似乎InnoDB在大多數其他數據庫下使用Oracle或「集羣」下的「索引組織表」。假設您不需要查詢「從父母到孩子」(即,「給我定的ID的所有關鍵字」),對CHILD_TABLE的PRIMARY KEY應該是:

{keyword, id} 

由於keyword是複合索引中的第一個字段,WHERE keyword = ...(或WHERE keyword LIKE 'prefix%')可以直接使用該索引。

+0

沒有自己的PK的innoDB表將表現得很差。 – Johan

+0

@Johan OK,我忘了提及這一點,但CHILD_TABLE的主鍵是:{id,keyword}。 –

+0

@Johan順便說一句,爲什麼它表現不佳(我不是MySQL/innoDB專家)? –