我有一个数据库中的表像这样 关键词有效的搜索查询
- ID INT(11)
- U_ID INT(11)
- 关键字文本
- CREATE_DATE INT的结构( 11)
U_ID为外键,id是主键
关键字字段是用户创建的用逗号分隔的单词列表 我想知道是否有人可以建议有效的查询来搜索这样的表。
我有一个数据库中的表像这样 关键词有效的搜索查询
U_ID为外键,id是主键
关键字字段是用户创建的用逗号分隔的单词列表 我想知道是否有人可以建议有效的查询来搜索这样的表。
如果使用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很多快得多。
谢谢,我认为这将简化事情 – MrFoh
您应该更改数据库设计,以便拥有一个名为user_keyword
的表并将每个关键字存储在单独的行中。然后,您可以索引此表并轻松地和有效地搜索它:
WHERE keyword = 'foo'
如果不能修改数据库那么你可以使用FIND_IN_SET
但它不会是非常有效:
WHERE FIND_IN_SET('foo', keywords)
你有2种选择:
SELECT * FROM Keywords WHERE keyword LIKE %KEYWORD%
错误的答案,在一个带有“book,testing”的CSV列中,即使'test'本身不在该列中,这也会给出匹配。在SQL和php中混合查询本身就是一种反模式。 – Johan
单独的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%'
)可以直接使用该索引。
没有自己的PK的innoDB表将表现得很差。 – Johan
@Johan OK,我忘了提及这一点,但CHILD_TABLE的主键是:{id,keyword}。 –
@Johan顺便说一句,为什么它表现不佳(我不是MySQL/innoDB专家)? –
切勿在数据库中使用CSV。这是一个主要的罪恶! – Johan