2013-02-23 3 views
6

J'ai deux tablessomme Sélectionner et jointure

  • Bills: id amount reference

  • Transactions: id reference amount

La requête SQL suivante

SELECT 
    *, 
    (SELECT SUM(amount) 
    FROM transactions 
    WHERE transactions.reference = bils.reference) AS paid 
FROM bills 
GROUP BY id HAVING paid<amount 

était destiné à certaines lignes de la table Bills, en ajoutant une colonne paid avec la somme du montant des transactions associées. Cependant, cela ne fonctionne que lorsqu'il y a au moins une transaction pour chaque facture. Sinon, aucune ligne pour une facture sans transaction n'est renvoyée. Probablement, c'est parce que j'aurais dû faire une jointure interne!

Je les opérations suivantes:

SELECT 
    *, 
    (SELECT SUM(transactions.amount) 
    FROM transactions 
    INNER JOIN bills ON transactions.reference = bills.reference) AS paid 
FROM bills 
GROUP BY id 
HAVING paid < amount 

Cependant, cela renvoie la même valeur payée pour toutes les lignes! Qu'est-ce que je fais mal ?

Répondre

15

Utilisez une jointure gauche au lieu d'une sous-requête:

select b.id, b.amount, b.paid, sum(t.amount) as transactionamount 
from bills b 
left join transactions t on t.reference = b.reference 
group by b.id, b.amount, b.paid 
having b.paid < b.amount 

Edit:
Pour comparer la somme des transactions au montant , gérer la valeur nulle que vous obtenez lorsqu'il n'y a pas de transactions:

having isnull(sum(t.amount), 0) < b.amount 
+1

Mais il n'y a pas de colonne "payée" dans "Bills", cela doit être défini comme la somme du montant des transactions.Si j'essaie de le modifier pour corriger cela, je n'ai toujours que la ligne "Bills" avec au moins une transaction. – Klaus

+0

@Klaus: Je vois, c'est là que vous avez obtenu cela de ... La somme sera nulle s'il n'y a pas de transactions, vous devrez donc gérer cela. Voir le code ci-dessus. – Guffa

+0

Merci beaucoup, le 'ifnull' (pas' isnull') et la jointure gauche ont fait l'affaire! – Klaus

2

Vous avez besoin d'un RIGHT JOIN pour inclure toutes les lignes de facture.

EDIT Ainsi, la requête finale sera

SELECT 
    *, 
    (SELECT SUM(transactions.amount) 
    FROM transactions 
    WHERE transactions.reference = bills.reference) AS paid 
FROM bills 
WHERE paid < amount 
+0

qui renverra la somme de toutes les transactions pour toutes les factures. – Guffa

+0

Il y a toujours le même problème que lors de ma deuxième tentative, comme le décrit @Guffa. – Klaus

+0

Et si vous remplacez "INNER JOIN bills ON" par "WHERE" – dotNET

0

Je sais que ce fil est vieux, mais je suis venu ici aujourd'hui parce que je rencontre le même problème.

S'il vous plaît voir un autre poste avec la même question: Sum on a left join SQL

Comme la réponse dit, utilisez GROUP BY sur la table à gauche. De cette façon, vous récupérez tous les enregistrements de la table de gauche, et cela résume les lignes correspondantes de la table de droite.

Essayez d'utiliser ceci:

SELECT 
    *, 
    SUM(transactions.sum) 
FROM 
    bills 
RIGHT JOIN 
    transactions 
ON 
    bills.reference = transactions.reference 
WHERE 
    transactions.sum > 0 
GROUP BY 
    bills.id 
Questions connexes