Oltre ai commenti e alle risposte che ti sono già stati forniti, credo che tu abbia enormemente complicato la tua procedura. Stai facendo le cose in modo molto procedurale, piuttosto che pensare in serie come dovresti essere. Stai anche ottenendo le colonne aggregate in tre query che sono essenzialmente identiche (ad es. stesse tabelle, condizioni di unione e predicati):puoi combinarle tutte per ottenere i tre risultati in un'unica query.
Sembra che tu stia tentando di inserire nella tabella clienthistoricalpurchases se non esiste già una riga per quel client, altrimenti aggiorni la riga. Questo mi urla immediatamente "dichiarazione MERGE".
Combinando tutto ciò, penso che la tua procedura attuale dovrebbe contenere solo una singola istruzione di unione:
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;
Tuttavia, ho alcune preoccupazioni sulla tua logica e/o modello di dati attuale.
Sembra che ti aspetti che venga visualizzata al massimo una riga per clientid in clienthistoricalpurchases. Cosa succede se un clientid ha due o più ordini diversi? Attualmente sovrascriveresti qualsiasi riga esistente.
Inoltre, vuoi davvero applicare questa logica a tutti gli ordini ogni volta che viene eseguito?