Oprócz komentarzy i odpowiedzi, które już otrzymałeś, uważam, że znacznie skomplikowałeś swoją procedurę. Robisz rzeczy bardzo proceduralnie, zamiast myśleć w zestawach tak, jak powinieneś. Otrzymujesz również zagregowane kolumny w trzech zapytaniach, które są zasadniczo identyczne (np. te same tabele, warunki złączenia i predykaty) - możesz połączyć je wszystkie, aby uzyskać trzy wyniki w jednym zapytaniu.
Wygląda na to, że próbujesz wstawić do tabeli clienthistoricalpurchases, jeśli wiersz nie istnieje dla tego klienta, w przeciwnym razie zaktualizujesz wiersz. To od razu krzyczy do mnie „oświadczenie MERGE”.
Łącząc to wszystko, myślę, że twoja bieżąca procedura powinna zawierać tylko jedną instrukcję scalania:
MERGE INTO clienthistoricalpurchases tgt
USING (SELECT clients.client_id,
COUNT(DISTINCT od.productid) distinct_products,
COUNT(od.productid) total_products,
SUM((od.unitprice * od.quantity) - od.discount) proposed_new_balance
FROM orderdetails od
INNER JOIN orders
ON orderdetails.orderid = orders.orderid
INNER JOIN clients
ON orders.clientid = clients.clientid
GROUP BY clients.client_id) src
ON (tgt.clientid = src.client_id)
WHEN NOT MATCHED THEN
INSERT (tgt.clientid,
tgt.distinctproducts,
tgt.totalproducts,
tgt.totalcost)
VALUES (src.clientid,
src.distinct_products,
src.total_products,
src.proposed_new_balance)
WHEN MATCHED THEN
UPDATE SET tgt.distinctproducts = src.distinct_products,
tgt.totalproducts = src.total_products,
tgt.totalcost = src.proposed_new_balance;
Mam jednak pewne obawy dotyczące Twojej obecnej logiki i/lub modelu danych.
Wygląda na to, że oczekujesz co najwyżej jednego wiersza na identyfikator klienta w historycznych zakupach klienta. Co jeśli klient ma dwa lub więcej różnych zamówień? Obecnie nadpisałbyś dowolny istniejący wiersz.
Czy na pewno chcesz zastosować tę logikę do wszystkich zamówień za każdym razem, gdy zostanie uruchomiona?