我在数据库中有一个表,结构如下 关键字
U_id是外键,id是主键
关键字字段是由逗号分隔的用户创建的字词列表 我想知道是否有人可以提出有效的查询来搜索这样的表格。
答案 0 :(得分:2)
您应该更改数据库设计,以便拥有一个名为user_keyword
的表,并将每个关键字存储在一个单独的行中。然后,您可以将此表编入索引并轻松有效地进行搜索:
WHERE keyword = 'foo'
如果您无法修改数据库,那么您可以使用FIND_IN_SET
,但效率不高:
WHERE FIND_IN_SET('foo', keywords)
答案 1 :(得分: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%'
)可以直接使用此索引。
答案 2 :(得分: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快得多。
答案 3 :(得分:-1)
您有两个选择:
SELECT * FROM Keywords WHERE keyword LIKE %KEYWORD%