2009-01-13 152 views
3

我對MySQL的使用非常基本。簡單的東西很容易,但我遇到了一些需要更多知識的東西。我需要一張儲存一小部分單詞的表格。存儲的字數可以是1到15之間的任何值。稍後,我計劃通過這些字搜索表格。我想過幾種不同的方法:我可以用15個字段創建數據庫,只要數據小於15就用空值填充字段。我不太喜歡這個。看起來效率很低。帶有動態數量的字段的MySQL設計

B.)另一種選擇是隻使用一個字段,並將數據存儲爲以逗號分隔的列表。每當我回來搜索時,我都會在該字段上運行正則表達式。同樣,這看起來效率很低。

我希望有一個很好的選擇這兩個選項。任何建議將非常感激。

-Thanks

回答

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代表每個類別。剩餘的字段代表一個類別成員,每個類別可以有不同數量的這些成員。

+0

太棒了!其實真的很有趣。 – objectivesea 2009-01-13 16:39:34

0

你是對的,A不好。 B也不好,因爲它不符合第一範式(每個字段必須是原子的)。您的示例中沒有任何內容表明您可以通過避免1NF獲益。

您需要一個表格來顯示您的單詞列表,並在每行中顯示每個單詞。

0

我會創建一個帶有ID和一個字段的表格,然後將結果存儲爲多個記錄。這提供了許多好處。例如,你可以用編程的方式強制你的15個字的限制,而不是在你的設計中做,所以如果你改變主意,它應該是相當容易的。您的查詢數據搜索速度也會快得多,正則表達式需要花費大量時間(比較)。另外使用字段的varchar可以讓你更好地壓縮你的表格。使用這種設計,在桌上索引應該更容易(更高效)。

0

做額外的工作並將15個單詞存儲爲15行,即對數據進行標準化。它可能需要你重新考慮你的策略,但當客戶出現時,請相信我,並說:「你能將這15個限制改爲20 ...」,你會很高興你做到了。

1

還有哪些其他數據與這些詞相關聯?

處理這類問題的一種典型方法最好用示例來描述。假設您的表格捕獲某些文檔中的特定單詞。一種典型的方式是爲每個文檔分配一個標識符。讓我們假設,就目前而言,每個文檔是一個Web URL,這樣你就會有一個表是這樣的:

CREATE TABLE WebPage (
    ID INTEGER NOT NULL, 
    URL VARCHAR(...) NOT NULL 
) 

你的話表可能是這個樣子:

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 

或類似。

0

取決於你想要完成什麼:

  1. 使用全文索引你的字符串表

  2. 三個表:一個是原始字符串,一個獨特的單詞(後詞根?)和一個連接表。這也可以讓你做更復雜的搜索,比如「返回所有包含以下五個單詞中的至少三個的所有字符串」或「返回'狗'之後發生'狐狸'的所有字符串」。

    CREATE TABLE串( ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 串TEXT NOT NULL )

    CREATE TABLE字( ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 字VARCHAR(14)NOT NULL UNIQUE , UNIQUE INDEX(字ASC) )

    CREATE TABLE word_string( ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY, string_id INT NOT NULL, word_i d 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串(串)VALUES ( '這是一個測試字符串'), (「快速赤狐跳過了懶惰的棕色狗 ')

    INSERT INTO字(詞)VALUES (' 本 '), (' 測試 '), (' 字符串 '), (' 快 '), (' 紅'), ('fox'), ('jump'), ('over'), ('lazy'), ( '棕色'), ( '狗')

    INSERT INTO word_string(string_id,word_id,word_order)VALUES (0,0,0), (0,1,3), (0, (1,3,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' 和 '快速' 的所有字符串 SELECT UNIQUE string.id,string.string FROM 串 INNER JOIN word_string ON string.id = word_string.string_id INNER JOIN字AS狐ON fox.word = '狐狸' AND word_string.word_id = fox.id INNER JOIN字AS QUICK ON quick.word =「快」 AND word_string.word_id = word.id

1

Hurpe,是你描述你將有一個數據庫表列中的場景,可以包含多達15個關鍵字。稍後,您將使用這些關鍵字來搜索大概會有其他列的表格?

那麼是不是有一個單獨的關鍵字表的答案?您還需要在關鍵字和主表格之間建立多對多的關係。

因此,使用汽車爲例,字表將存儲15個左右的關鍵字將具有以下結構:

ID    int 
Word   varchar(100) 

的CAR表將有一個結構是這樣的:

ID    int 
Name   varchar(100) 

然後最後你需要一個CAR_WORD表來保存許多一對多的關係:

ID    int 
CAR_ID   int 
WORD_ID   int 

個樣本數據去用這個字表:

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') 

唷!沒有打算寫太多,看起來很複雜,但是我總是看起來最終會陷入困境,儘管我試圖簡化事情。