我对MySQL的经验非常基础。简单的东西很容易,但我遇到了需要更多知识的东西。我需要一个存储一小部分单词的表。存储的单词数量可以是1到15之间的任何值。后来,我打算用这些单词在表格中搜索。我考虑过几种不同的方法:
A。)我可以用15个字段创建数据库,只要数据小于15就填充空值。我真的不喜欢这个。这看起来效率很低。
B。)另一种选择是只使用一个字段,并将数据存储为逗号分隔列表。每当我回到搜索时,我都会在场上运行正则表达式。再次,这似乎效率很低。
我希望这两个选项有一个很好的选择。任何建议都将非常感激。
-Thanks
答案 0 :(得分:15)
C)使用normal form;使用适当键的多行。一个例子:
mysql> SELECT * FROM blah;
+----+-----+-----------+
| K | grp | name |
+----+-----+-----------+
| 1 | 1 | foo |
| 2 | 1 | bar |
| 3 | 2 | hydrogen |
| 4 | 4 | dasher |
| 5 | 2 | helium |
| 6 | 2 | lithium |
| 7 | 4 | dancer |
| 8 | 3 | winken |
| 9 | 4 | prancer |
| 10 | 2 | beryllium |
| 11 | 1 | baz |
| 12 | 3 | blinken |
| 13 | 4 | vixen |
| 14 | 1 | quux |
| 15 | 4 | comet |
| 16 | 2 | boron |
| 17 | 4 | cupid |
| 18 | 4 | donner |
| 19 | 4 | blitzen |
| 20 | 3 | nod |
| 21 | 4 | rudolph |
+----+-----+-----------+
21 rows in set (0.00 sec)
这是我在关于group_concat
的其他问题中发布的表格。您会注意到每行都有一个唯一键K
。还有另一个键grp
代表每个类别。剩下的字段代表一个类别成员,每个类别可以有不同数量的这些。
答案 1 :(得分:1)
这些词还有哪些其他数据?
通过示例可以最好地描述处理此类问题的一种典型方法。我们假设您的表格捕获了某些文档中的某些单词。一种典型的方法是为每个文档分配一个标识符。让我们暂时假装每个文档都是一个Web URL,所以你有一个像这样的表:
CREATE TABLE WebPage (
ID INTEGER NOT NULL,
URL VARCHAR(...) NOT NULL
)
您的Words表格可能如下所示:
CREATE TABLE Words (
Word VARCHAR(...) NOT NULL,
DocumentID INTEGER NOT NULL
)
然后,对于每个单词,您在表中创建一个新行。要查找特定文档中的所有单词,请选择文档的ID:
SELECT Words.Word FROM Words, WebPage
WHERE Words.DocumentID = WebPage.DocumentID
AND WebPage.URL = 'http://whatever/web/page/'
要查找具有特定字词的所有文档,请按字词选择:
SELECT WebPage.URL FROM WebPage, Words
WHERE Words.Word = 'hello' AND Words.DocumentID = WebPage.DocumentID
或者其他一些。
答案 2 :(得分:1)
Hurpe,是您描述的场景,您将拥有一个数据库表,其中包含最多可包含15个关键字的列。稍后您将使用这些关键字来搜索可能还有其他列的表格?
那么关键字的单独表格不是答案吗?您还需要在关键字和主表之间建立多对多的关系。
因此,以汽车为例,将存储15个左右关键字的WORD表具有以下结构:
ID int
Word varchar(100)
CAR表的结构类似于:
ID int
Name varchar(100)
然后最后你需要一个CAR_WORD表来保存多对多关系:
ID int
CAR_ID int
WORD_ID int
并为WORD表提供示例数据:
ID Word
001 Family
002 Sportscar
003 Sedan
004 Hatchback
005 Station-wagon
006 Two-door
007 Four-door
008 Diesel
009 Petrol
与CAR表的样本数据一起
ID Name
001 Audi TT
002 Audi A3
003 Audi A4
然后交集CAR_WORD表样本数据可以是:
ID CAR_ID WORD_ID
001 001 002
002 001 006
003 001 009
为奥迪TT提供了正确的特性。
最后要搜索的SQL类似于:
SELECT c.name
FROM CAR c
INNER JOIN CAR_WORD x
ON c.id = x.id
INNER JOIN WORD w
ON x.id = w.id
WHERE w.word IN('Petrol', 'Two-door')
唷!不打算开始写这么多,它看起来很复杂,但它总是似乎最终我努力简化事情。
答案 3 :(得分:0)
你是对的,A是不好的。 B也不好,因为它不能遵守第一范式(每个字段必须是原子的)。你的例子中没有任何内容表明你会通过避免1NF而获益。
你想要一个表格,列出你自己行中每个单词的单词列表。
答案 4 :(得分:0)
我会创建一个带有ID和一个字段的表,然后将结果存储为多个记录。这提供了许多好处。例如,您可以以编程方式强制执行15个字的限制,而不是在设计中执行此操作,因此如果您改变主意,它应该相当容易。您搜索数据的查询运行起来也会快得多,正则表达式需要花费大量时间才能运行(相对而言)。另外,使用varchar作为字段将允许您更好地压缩表。使用此设计,表格上的索引应该更容易(更有效)。
答案 5 :(得分:0)
执行额外的工作并将15个字存储为表中的15行,即标准化数据。它可能需要你稍微重新考虑一下你的策略,但是当客户出现并且说“你能将那15个限制改为20 ......”时,请相信我,你会很高兴你做到了。
答案 6 :(得分:0)
取决于您想要完成的目标:
在字符串表上使用全文索引
三个表:一个用于原始字符串,一个用于唯一字(在生根后?)和连接表。这也可以让你做更复杂的搜索,例如“返回包含以下五个单词中至少三个的所有字符串”或“返回'dog'之后'狐狸'出现的所有字符串”。
CREATE TABLE字符串( id INT NOT NOT AUTO_INCREMENT PRIMARY KEY, string TEXT NOT NULL )
创建表字( id INT NOT NOT AUTO_INCREMENT PRIMARY KEY, word VARCHAR(14)NOT NULL UNIQUE, 独特的索引(字ASC) )
CREATE TABLE word_string( id INT NOT NOT AUTO_INCREMENT PRIMARY KEY, string_id INT NOT NULL, word_id INT NOT NULL, word_order INT NOT NULL, FOREIGN KEY(string_id)REFERENCES(string.id), FOREIGN KEY(word_id)REFERENCES(word.id), INDEX(word_id ASC) )
//示例数据 INSERT INTO string(string)VALUES ('这是一个测试字符串'), ('快速的红狐狸跳过懒惰的棕色狗')
插入单词(单词)值 ('这个'), ('测试'), ('串'), ('快'), ('红色'), ('狐狸'), ('跳'), ('过度'), ('懒'), ('棕色'), ( '狗')
INSERT INTO word_string(string_id,word_id,word_order)VALUES (0,0,0), (0,1,3), (0,2,4), (1,3,1), (1,4,2), (1,5,3), (1,6,4), (1,7,5), (1,8,7), (1,9,8), (1,10,9)
//示例查询 - 查找包含'fox'和'quick'的所有字符串 选择 UNIQUE string.id,string.string 从 串 INNER JOIN word_string ON string.id = word_string.string_id INNER JOIN单词AS fox ON fox.word ='fox'和word_string.word_id = fox.id INNER JOIN字AS快速开启quick.word ='快速'和word_string.word_id = word.id