2010-07-30 66 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