2010-07-30 6 views
1

OK Je vais essayer d'expliquer le mieux que je peux et peut-être que quelqu'un le comprendra. J'ai une application de CRM que je construis et ai les tables suivantes: contacts, email, téléphone, site Web et adresse. J'ai essayé de créer une requête qui rassemble toutes les informations dans un ensemble de résultats. J'ai trouvé un moyen qui fonctionne à 99,9% mais je pense qu'il me manque quelque chose pour que ce 1% fonctionne et je me suis tué en essayant de le trouver.Question MySQL "One to Many" question

Ma requête ressemble à ceci:

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 

Maintenant, comme je l'ai dit, il fonctionne comme 99,9% de la façon dont je veux qu'elle, mais ici est le jeu de résultats: (maintenant c'est un objet simulé de résultat, mais il suit ce qui est actuellement craché après la requête.)

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] => 
) 

maintenant que vous pouvez voir le résultat des actes comme je veux à l'exception de quand sur un des éléments a plusieurs éléments valides, soit dans ce cas John a 4 types de numéros de téléphone et cela provoque les autres enregistrements i n DB à multiplier en conséquence. Donc, dans ce cas, vous obtenez 4 du même article dans toutes les autres tables de soutien. J'ai essayé tout ce que je peux et peut-être que cela ne peut pas être fait mais j'ai pensé que j'essaierais une fois de plus et voir si quelqu'un le regarderait et dirait oh oui il te manque 5 lettres qui le feront fonctionner ou quelque chose. À ce stade, même un "votre stupide qui ne fonctionnera pas" serait génial aussi.

Merci encore pour toute aide que vous pouvez offrir!

MISE À JOUR:

Je me sens comme un Noob maintenant, je tire une erreur classique: j'ai vérifié mon résultat sans une vérification complète, mais en même temps par les renseignements fournis, il n'a pas été clair. Je vais expliquer ma solution originale a fonctionné sauf que quand j'avais 3 numéros de travail (type = 1) je finirais avec un résultat comme phone_type => 1 et phone => 555-1212,555-1213,555-1214 c'est bien, mais quand j'ai 2 travail et 1 maison les identifiants de type étaient inutiles, mais je n'ai jamais dit que vous pouvez avoir plus d'un type pour un contact alors en fait les deux de ma réponse ci-dessous sont corrects, cela dit le sql était Un peu mal formé mais je savais ce qu'il disait alors ça fonctionnait mieux et correct sur le nez. BTW juste tirant distint des champs de type ne le feraient pas non plus ... J'ai essayé cela.

Patial nouvelle solution de requête:

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 

Merci pour vos réponses, et comme une note de côté je viens annulé que les experts hors de prix eXchange cela est beaucoup plus facile à utiliser et trouver ce que vous recherchez et le meilleur de tout gratuit;) - merci encore.

+0

oh oui et le placement du groupe en était quelqu'un critique juste cas a problème similaire. – BrandonS

Répondre

2

Le problème est, dès que vous vous joignez sur PHONE (dans votre exemple), la requête renvoie quatre enregistrements. L'utilisation de GROUP_CONCAT dans la liste SELECT de niveau supérieur ne résoudra pas cela. La première solution qui vient à l'esprit est d'utiliser des requêtes internes pour garantir que vous ne retournerez qu'un seul enregistrement pour un contact donné.

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 ...] 

Cela devrait vous mettre sur la bonne voie, à moins que MySQL a très différent comportement sous-requête de MSSQL/Oracle ...

+0

merci l'homme que vous étiez bien travaillé parfaitement après que je me suis réellement assis et écouté ce que vous avez dit et a commencé à vérifier les résultats par rapport à ma fiche. Merci encore pour la solution. – BrandonS

0

Ne serait-il pas plus facile d'obtenir d'abord les informations de base de l'application (les champs qui ne se répètent pas), puis d'utiliser des requêtes séparées pour les informations récurrentes dans le formulaire principal? Ou, en guise de compromis, créez une vue qui affiche jusqu'à N nombre de champs répétitifs.

+0

Eh bien, c'est ce que je fais actuellement, mais je pensais que si je l'obtenais dans un ensemble de résultats unique, cela réduirait le stress sur le serveur si cela devenait un DB massif, je suppose que c'est la deuxième partie de ma question: juste mieux de le garder comme je l'ai ou verrais-je une augmentation de la performance de faire quelque chose comme ça? Merci pour votre réponse! – BrandonS

1

Jeter DISTINCT là-dedans.

GROUP_CONCAT (DISTINCT email.email_type COMMANDER PAR E-mail.EMAIL_TYPE) comme EMAIL_TYPE,

Ref

+0

bien je étais hors par 3 lettres DISTINCT est 8 mec je t'aime l'homme fonctionne parfaitement! impressionnant! – BrandonS

+0

je suis désolé pas votre faute, vous ne saviez pas que j'avais plusieurs types pour chaque enregistrement une meilleure explication est ci-dessus. Je voudrais pouvoir partager le crédit mais il a fait exactement ce dont j'avais besoin désolé encore. mais ta réponse était correcte. – BrandonS

+0

En fait j'aime mieux le sous-select aussi (jdacobson). Je suppose que l'optimiseur va faire un meilleur travail avec une sous-requête, puis lancer un DISTINCT dans tous ces éléments SELECT. Très heureux de voir un EE convertir :) –

Questions connexes