之前已经在这里问过这个问题的各种化身,但我想我会再给它一次。
我有一个糟糕的数据库布局。单个实体(小部件)分为两个表:
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%'...
,但这似乎很笨拙,我仍然不知道哪些字段匹配。我可以为我想要匹配的每个列运行一个单独的查询,这将给我所有匹配以及它们如何匹配,但这将是性能损失。任何想法?
答案 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类型的列。