Implement a Set-Based Approach Using CTEs and PIVOT: The most efficient solution leverages the power of CTEs and the PIVOT operator (available in SQL Server) to replace the WHILE loop. This approach pre-calculates all necessary values in a single pass, significantly improving performance.
WITH CalculationCTE AS (
-- This CTE performs all the calculations previously done in the loop
SELECT
pb.contract_id,
pb.system_id,
pb.premium_amount as payment_amount,
CASE
WHEN pm.total_premium = 0 THEN CAST(CASE WHEN ISNULL(pm.outstanding_premium,0) <> 0 THEN pm.outstanding_premium ELSE pm.premium_change END AS NUMERIC(18,3))
ELSE CASE
WHEN CAST(((CAST(CASE WHEN ISNULL(pm.outstanding_premium,0) <> 0 THEN pm.outstanding_premium ELSE pm.premium_change END AS NUMERIC(18,3)) / pm.total_premium) * pb.premium_amount) AS NUMERIC(18,2)) > CAST(CASE WHEN ISNULL(pm.outstanding_premium,0) <> 0 THEN pm.outstanding_premium ELSE pm.premium_change END AS NUMERIC(18,3)) AND CAST(CASE WHEN ISNULL(pm.outstanding_premium,0) <> 0 THEN pm.outstanding_premium ELSE pm.premium_change END AS NUMERIC(18,3)) > 0
THEN CAST(CASE WHEN ISNULL(pm.outstanding_premium,0) <> 0 THEN pm.outstanding_premium ELSE pm.premium_change END AS NUMERIC(18,3))
ELSE CAST(((CAST(CASE WHEN ISNULL(pm.outstanding_premium,0) <> 0 THEN pm.outstanding_premium ELSE pm.premium_change END AS NUMERIC(18,3)) / pm.total_premium) * pb.premium_amount) AS NUMERIC(18,2))
END
END as calculated_commission,
CASE
WHEN pm.total_premium = 0 THEN CAST(CASE WHEN ISNULL(pm.outstanding_premium,0) <> 0 THEN pm.outstanding_premium ELSE pm.premium_change END AS NUMERIC(18,3))
ELSE CAST(CASE WHEN ISNULL(pm.outstanding_premium,0) <> 0 THEN pm.outstanding_premium ELSE pm.premium_change END AS NUMERIC(18,3)) - CAST(((CAST(CASE WHEN ISNULL(pm.outstanding_premium,0) <> 0 THEN pm.outstanding_premium ELSE pm.premium_change END AS NUMERIC(18,3)) / pm.total_premium) * pb.premium_amount) AS NUMERIC(18,2))
END as calculated_outstanding,
pm.total_premium as total_amount,
ISNULL(pb.has_payment,0) as has_payment,
pb.process_date,
pb.transaction_id,
pb.original_transaction_id,
pb.created_date as payment_created_date_new,
ROW_NUMBER() OVER (PARTITION BY pb.contract_id, pb.system_id ORDER BY pb.created_date) as rn -- added row number for ranking
FROM payment_batch_temp pb
JOIN (SELECT SUM(CAST(CASE WHEN ISNULL(mt.outstanding_premium,0) <> 0 THEN mt.outstanding_premium ELSE mt.premium_change END AS NUMERIC(18,3))) OVER(PARTITION BY mt.contract_id,mt.system_id) as total_premium, mt.*
FROM (SELECT *, DENSE_RANK() OVER(PARTITION BY a.contract_id,a.system_id ORDER BY a.effective_date,a.expiration_date ASC,contract_year,transaction_ref_id) as date_rank
FROM policy_transaction_main a
WHERE batch_id = @current_batch_id AND processed_status IN ('N','2')
) mt
JOIN payment_batch_temp pi ON mt.contract_id = pi.contract_id AND mt.system_id = pi.system_id
AND (ISNULL(mt.premium_type,'STANDARD')) = ISNULL(pi.premium_type,'STANDARD')
WHERE mt.batch_id = @current_batch_id
AND CAST(CASE WHEN ISNULL(mt.outstanding_premium,0) <> 0 THEN mt.outstanding_premium ELSE mt.premium_change END AS NUMERIC(18,3)) <> 0
AND mt.record_type IN (1,4)
AND mt.processed_status IN ('N','2')
AND pi.batch_num = @min_batch
AND (ISNULL(pi.agent_id,0) = 0 OR ISNULL(pi.agent_id,0) = mt.agent_id)
AND date_rank = 1
) pm ON pb.contract_id = pm.contract_id AND pb.system_id = pm.system_id AND (ISNULL(pb.premium_type,'STANDARD')) = ISNULL(pm.premium_type,'STANDARD')
WHERE pm.batch_id = @current_batch_id
AND pm.total_premium <> 0
AND pm.record_type IN (1,4)
AND pm.processed_status IN ('N','2')
),
PivotedData AS (
SELECT *
FROM CalculationCTE
PIVOT (MAX(calculated_commission) FOR rn IN ([1],[2],[3], ...)) AS PivotTable --add as many columns as needed
)
UPDATE ptm
SET ptm.commission_premium = pd.calculated_commission,
ptm.outstanding_premium = pd.calculated_outstanding,
ptm.processed_status = CASE WHEN pd.calculated_outstanding = 0 AND pd.total_amount <> 0 AND pd.has_payment = 1 THEN '1' ELSE CASE WHEN pd.total_amount <> 0 AND pd.has_payment = 1 THEN '2' ELSE 'N' END END,
ptm.collected_premium = ptm.term_premium - pd.calculated_outstanding,
ptm.has_payment_flag = CASE WHEN pd.has_payment = 0 THEN 0 WHEN pd.total_amount <> 0 THEN 1 ELSE 0 END,
ptm.payment_process_date = pd.process_date,
ptm.payment_created_date = pd.payment_created_date_new,
ptm.process_step = 'STEP: 3',
ptm.notes = 'Applied payment processing for batch - ' + CAST(@current_batch_id AS VARCHAR(100))
FROM policy_transaction_main ptm
JOIN PivotedData pd ON ptm.record_id = pd.record_id;
INSERT INTO payment_processing_log (transaction_id)
SELECT transaction_id
FROM PivotedData;
UPDATE payment_batch_temp
SET processed_status = 1
WHERE transaction_id IN (SELECT transaction_id FROM payment_processing_log);