跨多个列的mysql关键字搜索

时间:2009-12-03 15:22:54

标签: mysql search keyword multiple-columns

之前已经在这里问过这个问题的各种化身,但我想我会再给它一次。

我有一个糟糕的数据库布局。单个实体(小部件)分为两个表:

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%'。这将给我所有黑色小部件或由blackwell行业或其他任何东西制作的小部件实例。我甚至会确切地知道哪个字段匹配,并且可以向我的用户显示。

如何使用新的表格布局执行类似的搜索?我当然可以做WHERE name LIKE '%black%' OR size LIKE '%black%'...,但这似乎很笨拙,我仍然不知道哪些字段匹配。我可以为我想要匹配的每个列运行一个单独的查询,这将给我所有匹配以及它们如何匹配,但这将是性能损失。任何想法?

3 个答案:

答案 0 :(得分:4)

您有两个相互矛盾的要求。您希望搜索所有数据都在一个字段中,但您还想确定哪个特定字段匹配。

您的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时间来维护等等。我不认为这是值得的。

答案 1 :(得分: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的值。

不确定它会如何影响性能。在投入生产之前可以免费测试

答案 2 :(得分:0)

您可能希望查看MySQL全文搜索功能,这使您可以匹配多个varchar类型的列。

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