2010-07-30 43 views
1

好吧我會盡力解釋這個最好的我可以,也許有人會理解它。我有一個我正在構建的CRM應用程序,並具有以下表格:聯繫人,電子郵件,電話,網站和地址。我一直在試圖創建一個將所有信息收集到一個結果集中的查詢。我找到了一種可以工作99.9%的方式,但我認爲我錯過了1%的工作,並且爲了找到它而殺了自己。MySQL查詢「一對多」的問題

我的查詢看起來是這樣的:

SELECT 
contacts.full_name, 
contacts.title, 
contacts.company, 
contacts.background, 
GROUP_CONCAT(email.email_type ORDER BY email.email_type)as email_type, 
GROUP_CONCAT(email.email ORDER BY email.email_type)as email, 
GROUP_CONCAT(phone.phone_type ORDER BY phone.phone_type)as phone_type, 
GROUP_CONCAT(phone.phone ORDER BY phone.phone_type)as phone, 
GROUP_CONCAT(website.website_type ORDER BY website.website_type)as website_type, 
GROUP_CONCAT(website.website ORDER BY website.website_type)as website, 
GROUP_CONCAT(address.type ORDER BY address.type) as address_type, 
GROUP_CONCAT(address.address_street ORDER BY address.type) as street, 
GROUP_CONCAT(address.address_city ORDER BY address.type) as city, 
GROUP_CONCAT(address.address_state ORDER BY address.type) as state, 
GROUP_CONCAT(address.address_zip ORDER BY address.type) as zip, 
GROUP_CONCAT(address.address_country ORDER BY address.type) as country 
FROM 
contacts 
Left Join email ON contacts.id = email.contact_id 
Left Join phone ON contacts.id = phone.contact_id 
Left Join website ON contacts.id = website.contact_id 
Left Join address ON contacts.id = address.contact_id 
GROUP BY 
contacts.id 
ORDER BY 
contacts.id ASC 

現在,就像我說的它像的方式99.9%我想它,但這裏是結果集: (現在這是一個模擬的結果對象,但它遵循什麼是目前查詢後吐了出來。)

stdClass Object 
(
    [full_name] => John Mueller 
    [title] => President 
    [company] => Mueller Co. 
    [background] => This is the contacts background info. 
    [email_type] => 1,1,1,1 
    [email] => [email protected],[email protected],[email protected],[email protected] 
    [phone_type] => 1,2,3,4 
    [phone] => (123) 555-1212,(123) 555-1213,(123) 555-1214,(123) 555-1215 
    [website_type] => 1,1,1,1 
    [website] => www.mc.com,www.mc.com,www.mc.com,www.mc.com 
    [address_type] => 1,1,1,1 
    [street] => {address_1},{address_1},{address_1},{address_1} 
    [city] => {city_1},{city_1},{city_1},{city_1} 
    [state] => {state_1},{state_1},{state_1},{state_1} 
    [zip] => {zip_1},{zip_1},{zip_1},{zip_1} 
    [country] => 
) 

現在你可以看到結果的行爲像我希望它除了當一個項目有多個有效項目,即在此情況下,約翰4種類型的電話號碼,這導致其他記錄我數據庫相應地相乘。所以在這種情況下,您在所有其他支持表中獲得4個相同的項目。

我嘗試了一切可能,也許它不能完成,但我想我會再試一次,看看有沒有人會看它,並說哦,你錯過了5個字母,這將使它工作或者其他的東西。在這一點上,即使是「你的愚蠢的行爲也不會有效」。

再次感謝任何人可以提供幫助!

UPDATE:

我現在覺得像這樣一個小白,我把一個典型的錯誤:我檢查了我的結果沒有完全驗證,但通過信息的同時,我公司提供的,目前還不清楚。我會解釋我的原始解決方案,除了當我有3個工作(type = 1)數字時,我最終會得到如phone_type => 1和phone => 555-1212,555-1213,555-1214的結果,這是好,但是當我有2個工作和1個家庭的類型標識符是無用的,但我從來沒有說過,你可以有多個任何類型的聯繫人,所以實際上我的答案下面是正確的,說那個SQL是一個有點畸形,但我知道他在說什麼,所以它實際上對鼻子更好,更正確。順便說一句,只是從類型字段拉伸distint不會這樣做......我試過了。

(ε2)新的查詢解決方案:

SELECT 

contacts.full_name, 
contacts.title, 
contacts.company, 
contacts.background, 

inner_phone.phone, 
inner_phone_type.phone_type 

FROM 
contacts 

left Join (SELECT phone.contact_id, GROUP_CONCAT(phone.phone ORDER BY phone.phone_type) as phone FROM phone GROUP BY phone.contact_id) inner_phone ON contacts.id = inner_phone.contact_id 
left Join (SELECT phone.contact_id, GROUP_CONCAT(phone.phone_type ORDER BY phone.phone_type) as phone_type FROM phone GROUP BY phone.contact_id) inner_phone_type ON contacts.id = inner_phone_type.contact_id 

ORDER BY 
contacts.id ASC 

謝謝您的解答,並作爲一個方面說明我只是取消了過高的專家交流是這樣更容易使用,並找到你在找什麼,最好的所有免費;) - 再次感謝。

+0

哦耶和GROUP BY的位置是以防萬一有人有關鍵類似的問題。 – BrandonS 2010-07-31 00:21:59

回答

2

的問題是,只要你加入手機上(在你的例子),該查詢返回四個記錄。在頂層SELECT列表中使用GROUP_CONCAT不會解決這個問題。想到的第一個解決方案是使用內部查詢來保證您只會爲給定聯繫人返回一條記錄。

SELECT 
contacts.full_name, 
[...] 
inner_phone.phones 
FROM contacts 
LEFT JOIN (SELECT GROUP_CONCAT(phone ORDER BY phone_type) AS phones, contact_id FROM phone) inner_phone ON contacts.ID = inner_phone.contact_id 
[... etc. for other tables ...] 

這應該把你在正確的軌道上,除非MySQL有從MSSQL/Oracle的完全不同的子查詢的行爲......

+0

謝謝你,當我坐下來,聽完你說的話並開始檢查我的主記錄結果後,你的工作完全正確。再次感謝解決方案。 – BrandonS 2010-07-31 00:18:22

0

首先將「基本」信息獲取到應用程序(不重複的字段),然後使用主表單中的子表單對重複信息使用單獨查詢更容易嗎?

或者,作爲折中,創建一個視圖,最多顯示N個重複字段。

+0

那麼這就是我目前正在做的,但我認爲,如果我把它放到一個單一的結果集,它會減輕服務器上的壓力,如果這成爲一個龐大的數據庫,我想這是我的問題的第二部分:如果它是隻是更好地保持它的方式,或者我會看到性能增加這樣做? 感謝您的回答! – BrandonS 2010-07-30 21:10:39

1

在那裏拋出DISTINCT。

GROUP_CONCAT(DISTINCT email.email_type ORDER BY email。EMAIL_TYPE)作爲EMAIL_TYPE,

Ref

+0

以及我被3個字母關了DISTINCT是8個傢伙我愛你的男人完美的作品!真棒! – BrandonS 2010-07-30 21:14:20

+0

我很抱歉不是你的錯,你不知道我有多個類型的每個記錄更好的解釋是上面。我希望我能分裂信貸,但他確實做了我需要再次抱歉的事情。但你的回答是正確的。 – BrandonS 2010-07-31 00:16:27

+0

其實我也更喜歡子選擇(jdacobson)。我猜想優化器會更好地處理子查詢,然後在所有這些SELECT項中引入DISTINCT。非常高興看到一個EE轉換:) – 2010-08-02 12:19:02