2012-02-23 57 views
4

我使用MySQL和我有一個成員表有BLOB「聯繫人」含其他成員的ID的逗號分隔列表字段:MySQL的選擇,隨後將其用逗號分隔的字段

TABLE members: 
id_member = 1 
firstname = 'John' 
contacts (BLOB) = '4,6,7,2,5' 

我要檢索的所有在個人的「聯繫人」列表中輸入名字,並帶有單個查詢。我試過如下:

SELECT firstname from members WHERE id_member IN (SELECT contacts FROM members WHERE id_member = 1); 

它僅返回一行,但當我嘗試:

SELECT firstname from members WHERE id_member IN (4,6,7,2,5); 

它從列表中返回所有的名字。我可以使用兩個查詢來實現這一點,但我想我會仔細檢查是否有一種方法可以讓它使用一個簡單,優雅的查詢。

感謝您的閱讀,任何幫助表示讚賞。 七月

+0

是您的ID數字和你的BLOB字符串? – Jrod 2012-02-23 19:41:16

+0

這裏的解決方案是使用一個聯繫人表格對數據庫進行正確的規範化處理,該聯繫人表格有兩列:id_member和id_contact,每個id_member有多行。 – 2012-02-23 19:41:37

+0

是的,Jrod,我的ID是INT,blob是一個字符串。感謝邁克爾的想法,但是我對這個選項有一個保留,我在我對Tadman的回答中表達了這個選項 – 2012-02-23 20:06:27

回答

2

你可以改變這個DB結構嗎?聯繫人字段確實應該是相關的表格而不是列。假設這種結構的聯繫人表:

id_contact 
id_member 

那麼你可以使用EXISTS來代替:

SELECT firstname from members m WHERE EXISTS (SELECT 1 FROM contacts c WHERE c.id_contact = m.id_member); 
+0

這是一個很好看的查詢。我正在尋找相關的表格,感謝您的幫助 – 2012-02-25 10:58:19

5

這似乎是一個非常貧窮的表設計。有沒有可能改變它?

如果你不能改變設計,那麼你可以通過使用FIND_IN_SET處理MySQL中的逗號分隔值,但它不會能夠有效地使用索引:

SELECT firstname 
FROM members 
WHERE FIND_IN_SET(id_member, (SELECT contacts FROM members WHERE id_member = 1)) 

但是,而不是走這條路,我會強烈建議,如果可能的話,你normalize your database。考慮使用join table而不是逗號分隔列表。然後,您可以使用連接找到所需的條目,並且搜索將能夠使用索引。

+0

我不知道有關FIND_IN_SET的問題,但我敢打賭,這對於大型數據集來說會很殘酷,因爲它的結果在自動錶掃描中不能被索引。巧妙的技巧,雖然。 – tadman 2012-02-23 19:43:39

+0

感謝您的研究環節,非常有幫助。我正在尋找一個標準化的db – 2012-02-25 10:57:38

3

如果您使用的是串行BLOB類型列來存儲這些值,那麼你就不會要能夠做你想做的。更友善的SQL方法是創建一個關係表,該關係表可以用作JOIN操作的一部分,例如member_contacts表,該表在一個id_member值與其他值之間有關聯。

擴展您的逗號分隔的列表爲單獨的記錄是一個非常簡單的機械過程。

+0

感謝所有的答覆。我考慮過這種方法,但收集單個成員的聯繫人列表的想法要求瀏覽填充了每個人的聯繫人條目的表格似乎效率低下。如果速度更快,我一定會去的 – 2012-02-23 19:52:48

+0

如果你在你的'WHERE'子句中使用的'id_member'上索引這個值,那麼即使在大量數據集上它實際上也是非常快的。對於任何頻繁的查詢總是有索引。 – tadman 2012-02-23 21:45:32

+0

謝謝,我結束了這樣做 – 2012-02-25 10:57:10