2010-12-10 6 views
0

J'ai deux tables "banque" et "liens". Chaque utilisateur a un enregistrement bancaire mais peut avoir 0, 1 ou plusieurs enregistrements d'obligations.MySQL Mettre à jour une valeur de champ avec sous-requête avec plusieurs lignes retournées

Je veux écrire un script qui met à jour le champ "cash" dans la table "bank" avec les intérêts des liens multiples qu'un utilisateur peut détenir. L'intérêt est calculé par les champs de coupon d'émission * du tableau "obligations". Mais comme un utilisateur peut détenir plusieurs liens, il devrait le faire pour chaque lien.

En ce moment, j'ai essayé quelque chose comme ceci:

$MySQL->db_Query("UPDATE bonds bo, bank ba SET 
     ba.cash = ROUND(ba.cash + (bo.issuePrice * bo.coupon), 2), 
     ba.earned = ROUND(ba.earned + (bo.issuePrice * bo.coupon), 2) 
    WHERE LOWER(ba.user) = LOWER(bo.holder) AND 
     LOWER(bo.holder) <> LOWER('Bank');"); 

Mais il ne donne pas le résultat escompté. Je l'ai essayé avec un utilisateur avec 2 obligations, si les deux obligations devraient donner 500 intérêts chacune, donc un total de 1000, il ajoute seulement 500 comme il y a seulement 1 lien. Si je mets un intérêt de 500 obligations et l'autre avec un intérêt calculé de 1000, il ajoute soudain 475.

+2

Convert à un SELECT, et confirmer la sortie est ce que vous attendez –

Répondre

1

Il est probablement utile de vous assurer que votre instruction UPDATE essaie de mettre à jour la ligne de chaque utilisateur une seule fois. Une sous-requête est la meilleure façon de le faire, le plus efficacement mis en œuvre comme une table jointe:

UPDATE bank 
JOIN (SELECT LOWER(bonds.holder) as user, 
    SUM(bonds.issuePrice * bonds.coupon) as total 
    FROM bonds 
    WHERE LOWER(bonds.holder) != 'bank' 
    GROUP BY user 
) as increments ON increments.user = LOWER(bank.user) 
SET bank.cash = ROUND(bank.cash + increments.total, 2), 
    bank.earned = ROUND(bank.earned + increments.total, 2) 

(Pour plus d'optimisation, les appels inférieurs et RONDES devraient probablement être éliminés, mais c'est une autre discussion.)

+0

Merci, cela a fonctionné! –

0

La façon la plus directe et facile est d'utiliser des sous-requêtes et mettre à jour les champs individuellement ...

UPDATE bank ba1 
SET ba1.cash = ba1.cash + (ROUND(SELECT SUM(bo.issuePrice * bo.coupon) 
       FROM bank ba2 JOIN bonds bo ON bo.user = ba2.user 
       WHERE ba2.user = ba1.user), 2) 
... 
+0

Cela a fonctionné aussi mais je pense que l'autre requête est plus facile et plus performant. –

Questions connexes