2010-07-26 6 views
1

Je souhaite afficher tous les clients et leurs adresses, ainsi que le nombre et la somme totale de leurs commandes. Ma requête ressemble à ceci:Les fonctions agrégées renvoient des valeurs erronées lors de la jonction de plusieurs tables

select *, sum(o.tota), count(o.total) 
from customer c 
natural join orders o 
group by c.custId; 

qui fonctionne bien.

mais si j'ajoute une nouvelle table à la requête:

select *, sum(o.tota), count(o.total) 
from customer c 
natural join orders o 
natural join cust_addresses a 
group by c.custId; 

alors il ne fonctionnera plus. les fonctions agrégées renvoient des valeurs erronées car il peut y avoir plusieurs adresses par client, ce qui est correct, je veux également afficher toutes leurs adresses. Que puis-je faire pour résoudre le problème de la fonction d'agrégation?

je pourrais penser à faire quelque chose comme:

select *, (select total from orders o where o.custid=c.custid), .. 
from customer c 
natural join orders o 
natural join cust_addresses a 
group by c.custId; 

Mais cela est très lent.

EDIT je maintenant essayé ce qui suit, mais il me dit que c.custid sur le terrain est inconnu:

select * 
from 
    customer c,    
    left join (select sum(o.tota), count(o.total) from orders o where o.custid=c.custid) as o 
where ... 
group by c.custId; 
+0

Comment voulez-vous gérer les clients qui n'ont pas de commandes? Votre requête actuelle les omet –

+0

année à droite, j'ai oublié la gauche pour la gauche rejoindre :) – codymanix

Répondre

3

solution simple: utiliser deux requêtes.

Sinon, vous pouvez faire votre calcul agrégé dans une sous-requête (sur la table entière, pas par ligne) puis JOIN le résultat de la sous-requête avec la table d'adresses pour obtenir vos données supplémentaires. Essayez ceci:

SELECT * 
FROM customer T1 
LEFT JOIN 
(
    SELECT custId, 
      SUM(total) AS sum_total, 
      COUNT(total) AS count_total 
    FROM orders 
    -- WHERE ... 
    GROUP BY custId 
) T2 
ON T1.custId = T2.custId 
-- WHERE ... 
+0

Merci pour la réponse. Je l'ai essayé maintenant mais ça n'a pas marché pour moi. il semble que je ne peux pas accéder aux tables externes à partir de la sous-sélection. Voir mes modifications s'il vous plaît. – codymanix

+0

@codymanix: Vous ne pouvez pas accéder à un alias à partir d'une requête interne dans une requête externe. –

+0

Non Je souhaite accéder à un alias à partir de la requête externe dans la requête interne. Je veux utiliser le client c qui est défini dans la requête externe dans la clause where de la requête interne. – codymanix

0

Essayez quelque chose comme:

select c.custId, max(c.custName) custName, ... 
     a.addrId, max(a.addrLine1) addrLine1, ... 
     sum(o.total) order_total, count(o.total) order_count 
from customer c 
left join orders o on c.custId = o.custId 
left join cust_addresses a on c.custId = a.custId 
group by c.custId, a.addrId; 

vous supposant que vous voulez tous les clients, que ce soit ou non ils ont des ordres ou des adresses.

+0

Mais alors la somme et le compte ne sont pas affichés correctement si le client a plus d'une commande ou une adresse. – codymanix

+0

@codymanix, avez-vous inclus le champ clé cust_address (que j'ai appelé addrId, puisque vous n'avez pas posté la structure de la table) dans la clause group by de votre requête? Si c'est le cas, la somme et le nombre doivent être retournés correctement. –

+0

mais j'ai plusieurs lignes pour un client retourné. – codymanix