2010-04-11 7 views
3

J'ai 3 tables qui sont quelque chose comme ça (simplifié ici ofc):mySQL un à plusieurs requêtes

  • utilisateurs
    • user_id
    • user_name
  • info
    • info_id
    • user_id
    • taux
  • contacts
    • contact_id
    • user_id
    • contact_data

utilisateurs a une à une relation avec des informations, bien que info faire Il n'y a pas toujours d'entrée associée.

Les utilisateurs ont une relation un-à-plusieurs avec les contacts, bien que les contacts n'aient pas toujours d'entrées associées.

Je sais que je peux saisir le bon 'users' + 'info' avec une jointure à gauche, y at-il un moyen d'obtenir toutes les données que je veux à la fois?

Par exemple, un enregistrement retourné pourrait être:

user_id: 5 
user_name: tom 
info_id: 1 
rate: 25.00 
contact_id: 7 
contact_data: 555-1212 
contact_id: 8 
contact_data: 555-1315 
contact_id: 9 
contact_data: 555-5511 

Est-ce possible avec une seule requête? Ou dois-je utiliser plusieurs?

Répondre

2

Chaque ligne de résultat doit avoir les mêmes colonnes, donc vous ne pouvez pas agréger plusieurs lignes de contact n'ayant pas les autres colonnes.

Il faut espérer que cette requête obtenir ce dont vous avez besoin:

SELECT 
    u.user_id as user_id, 
    u.user_name as user_name, 
    i.info_id as info_id, 
    i.rate as rate, 
    c.contact_id as contact_id, 
    c.contact_data as contact_data 
FROM users as u 
LEFT JOIN info as i ON i.user_id = u.user_id 
LEFT JOIN contacts as c ON c.user_id = u.user_id 
+1

Je viens de construire une requête réelle sur ma base de données et elle produit une tonne de données redondantes, ce qui me donne toutes les données dont j'ai besoin, mais semble être trop. Je pense que je vais aller avec la méthode de deux requêtes, mais c'était bien d'apprendre comment construire une requête avec plusieurs jointures correctement. – Stomped

5

Il est possible de faire ce que vous demandez dans une requête, mais vous auriez besoin soit un nombre variable de colonnes qui est mal parce que SQL n'est pas conçu pour cela, ou vous devez avoir un nombre fixe de colonnes, ce qui est encore pire car il n'y a pas de nombre fixe de colonnes que vous pouvez choisir.

Je suggère d'utiliser l'une des deux alternatives:

1. Renvoyez une ligne pour chaque donnée de contact, en répétant les données dans d'autres colonnes:

 
5 tom 1 25.00 7 555-1212 
5 tom 1 25.00 8 555-1315 
5 tom 1 25.00 9 555-5511 

Le problème avec cela est bien sûr que les données redondantes sont normalement une mauvaise idée, mais si vous n'avez pas trop de données redondantes, ce sera OK. Utilisez votre jugement ici.

2. Utilisez deux requêtes. Cela signifie un temps d'exécution légèrement plus long, mais moins de données à transférer.

Dans la plupart des cas, je préférerais la deuxième solution.

Vous devriez essayer d'éviter de faire un grand nombre de requêtes à l'intérieur d'une boucle. Cela peut presque toujours être réécrit en une seule requête. Mais si l'utilisation de deux requêtes est la manière la plus naturelle de résoudre votre problème, utilisez simplement deux requêtes. N'essayez pas de regrouper toutes les données dont vous avez besoin en une seule requête uniquement dans le but de réduire le nombre de requêtes.