2012-04-30 2 views
6

Je crois que je peux optimiser cette instruction sql en utilisant une instruction case pour les jointures externes gauches.Optimisation SQL Instruction

Mais j'ai eu du mal à mettre en place les cas, un pour résumer les types de code AB, CD et un autre pour Tout le reste.

Appréciez toute aide ou des conseils que vous pouvez me donner à ce sujet.

update billing set payments = isnull(bd1.amount, payments) 
, payments = case 
     when payments is null then 0 
     else payments 
    end 
, charges = case 
     when bd2.amount is not null then charges 
     when charges is null then 0 
     else charges 
     end 
, balance = round(charges + isnull(bd1.amount, bi.payments), 2) 
from billing bi 

left outer join (select inv, round(sum(bd1.bal), 2) amount 
       from "bill" bd1 
       where code_type = 'AB' 
       or code_type = 'CD' 
       group by inv) bd1 
       on bd1.inv = bi.inv 
left outer join (select invoice, round(sum(bd2.bal), 2) amount 
       from "bill" bd2 
       where code_type <> 'AB' 
       and code_type <> 'CD' 
       group by inv) bd2 
       on bd2.inv = bi.inv; 
+3

Est-ce valide? Vous semblez mettre à jour la colonne 'payments' deux fois. –

+0

@Siva J'utilise Avantage 9 – Trevor

Répondre

5

Vous pouvez le simplifier pour utiliser une seule requête plutôt que deux. Vous avez toujours besoin de l'un parce qu'un GROUP BY dans un UPDATE ne fonctionne pas.

UPDATE bi 
SET payments = bd.payments, 
     charges= bd.charges, 
     balance = bd.balance 
FROM billing bi 
     LEFT JOIN (SELECT bd.inv, 
         payments = Round(Sum(CASE 
               WHEN code_type IN ('AB' , 'CD') THEN 
               bd.bal 
               ELSE 0 
               END), 2), 
         charges = Round(Sum(CASE 
               WHEN code_type NOT IN ('AB' , 'CD') THEN 
               bd.bal 
               ELSE 0 
              END), 2), 
         balance = Round(Sum(bd.bal), 2) 
        FROM bill bd 
        GROUP BY bd.inv) bd 
     ON bd.inv = bi.inv 
+0

Cette syntaxe n'est pas valide. Vous ne pouvez pas avoir une fonction d'agrégat directement dans la liste des ensembles. – GarethD

+0

@GarethD oui c'est pourquoi je l'ai corrigé, voir ma dernière édition –

+0

Ouais, désolé, j'ai commencé à écrire le commentaire, puis vérifié pour être sûr à 100% que ce n'était pas valide, donc au moment où j'ai posté vous l'aviez déjà corrigé . Vous pourriez améliorer cela en utilisant 'CASE WHEN Code_Type IN ('AB', 'CD')' Plutôt que 'Code_Type = 'AB' OU Code_Type = 'CD'' – GarethD

1

Peut-être quelque chose comme ceci:

update billing set payments = isnull(bd1.amount, payments) 
, payments = isnull(payments, 0) 
, charges = isnull(bd2.amount, isnull(charges, 0)) 
, balance = round(charges + isnull(bd1.amount, bi.payments), 2) 
from billing bi 

left outer join (select inv, round(sum(bd1.bal), 2) amount 
       from "bill" bd1 
       where code_type in ('AB', 'CD') 
       group by inv) bd1 
       on bd1.inv = bi.inv 
left outer join (select invoice, round(sum(bd2.bal), 2) amount 
       from "bill" bd2 
       where code_type not in ('AB', 'CD') 
       group by inv) bd2 
       on bd2.inv = bi.inv; 

Les deux gauche jointures ne sont pas un problème!