2012-04-30 23 views
6

Wierzę, że mogę zoptymalizować to wyrażenie sql, używając instrukcji case dla Left Outer Joins.Optymalizacja SQL Case statement

Ale miałem trudny czas ustawiania skrzynek, jeden do podsumowania typów kodów AB, CD i inny dla wszystkich pozostałych.

Doceniam każdą pomoc lub wskazówki, które możesz mi w tej sprawie udzielić.

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

Czy to jest ważne? Wygląda na to, że dwukrotnie aktualizujesz kolumnę 'payments'. –

+0

@Siva Używam Advantage 9 – Trevor

Odpowiedz

5

Można to uprościć, aby użyć pojedynczego zapytania zamiast dwóch. Nadal potrzebujesz tego, ponieważ GROUP BY w UPDATE nie działa.

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

To nie jest poprawna składnia. Nie możesz mieć funkcji agregującej bezpośrednio na liście zestawów. – GarethD

+0

@ GarethD yep, dlatego to naprawiłem, zobacz moją ostatnią edycję –

+0

Tak, przepraszam, zacząłem pisać komentarz, a następnie sprawdziłem, czy mam 100% pewności, że to nie jest poprawne, więc do czasu, kiedy to opublikowałem, już to naprawiłeś . Możesz poprawić to dalej, używając 'CASE WHEN Code_Type IN ('AB', 'CD')' Zamiast 'Code_Type = 'AB' OR Code_Type = 'CD'' – GarethD

1

Może coś takiego:

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; 

Dwie lewe przyłącza nie są problemem!