2009-12-03 140 views
1

這個問題的各種形式已經在這裏提到過,但我想我會再試一次。跨多列的mysql關鍵字搜索

我有一個可怕的數據庫佈局。一個單一實體(插件)分成兩個表:

CREATE TABLE widgets (widget_id int(10) NOT NULL auto_increment)

CREATE TABLE widget_data ( widget_id int(10), field ENUM('name','size','color','brand'), data TEXT)

這是小於理想。如果想要查找特定名稱,顏色和品牌的小部件,我必須在widget_data表上執行三向加入。所以我轉換成合理的表類型:

CREATE TABLE widgets (widget_id int(10) NOT NULL auto_increment, name VARCHAR(32),size INT(3),color VARCHAR(16), brand VARCHAR(32))

這使得大部分查詢好得多。但它使搜索更難。它曾經是,如果我想要搜索小部件,例如'%black%',我只需要SELECT * FROM widget_data WHERE data LIKE '%black%'。這會給我所有黑色部件的實例,或黑洞行業或任何其他部件。我甚至可以確切地知道哪個字段匹配,並且可以顯示給我的用戶。

如何使用新的表格佈局執行類似的搜索?我當然可以做WHERE name LIKE '%black%' OR size LIKE '%black%'...,但看起來很笨重,我仍然不知道哪些字段匹配。我可以爲每一個我想匹配的列運行一個單獨的查詢,這會給我所有的匹配以及它們如何匹配,但那會是一個性能問題。有任何想法嗎?

回答

3

您有兩個相沖突的要求。您想要搜索就好像您的所有數據都位於單個字段中一樣,但您也希望識別哪個特定字段已匹配。

您的WHERE name LIKE '%black%' OR size LIKE '%black%'...表達式沒有什麼不對。如您所定義的那樣,這是對錶格的完全有效搜索。爲什麼不只是檢查代碼中的結果以查看哪一個匹配?這是一個很小的開銷。

如果你想爲你的SQL一個更清晰的語法,那麼你可以在表上創建一個視圖,將它由串聯的其他領域的一個額外的字段:

CREATE VIEW extra_widget_data AS 
    SELECT (name, size, color, brand, 
      CONCAT(name, size, color, brand) as all_fields) 
    FROM widget_data; 

然後,你必須添加一個在這個領域的索引,這需要更多的空間,CPU時間來維護等。我不認爲這是值得的。

0

您可能想查看MySQL全文搜索功能,這使您可以匹配多列varchar類型。

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

+1

有問題的表是innodb,不能更改爲myisam,所以全文索引不幸成爲選項 – 2009-12-03 15:27:44

+0

全文索引可以與InnoDB或MyISAM表一起使用,並且只能爲CHAR,VARCHAR創建或TEXT列。 – 2018-01-06 05:16:07

2

可以包括WHERE表達式的一部分到選擇列。例如:

SELECT 
    *, 
    (name LIKE '%black%') AS name_matched, 
    (size LIKE '%black%') AS size_matched 
FROM widget_data 
WHERE name LIKE '%black%' OR size LIKE '%black%'... 

然後在腳本的側檢查name_matched值。

不知道它將如何影響性能。 Feel在開始生產之前可以自由測試它