You might consider the following strategy if you’re looking for a faster or more efficient approach, especially for large datasets.
1> Filter Eligible Products: Use a series of JOIN operations to directly filter and transform the data.
2> Compute Scores and Sort: Combine, compute scores, and sort in a more straightforward manner.
3> Extract Top Scores: Use aggregation and subqueries to get the lowest scores.
-- Filter eligible products and calculate scores
WITH FilteredScores AS (
SELECT
A.CUST_NO,
COALESCE(NULLIF(B.DF_NOCA_FP, 0), 0) * A.ca_enpv AS ca_enpv,
COALESCE(NULLIF(B.DF_NoCC, 0), 0) * A.cc_enpv AS cc_enpv,
COALESCE(NULLIF(B.DF_NoHI, 0), 0) * A.hi_enpv AS hi_enpv,
COALESCE(NULLIF(B.DF_NOLI, 0), 0) * A.in_enpv AS in_enpv,
COALESCE(NULLIF(B.DF_NoInv, 0), 0) * A.mg_enpv AS mg_enpv,
COALESCE(NULLIF(B.DF_NoMTG, 0), 0) * A.pl_enpv AS pl_enpv,
COALESCE(NULLIF(B.DF_NoLOA, 0), 0) * A.pr_enpv AS pr_enpv,
COALESCE(NULLIF(B.DF_NoSAV, 0), 0) * A.sv_enpv AS sv_enpv
FROM TableA A
JOIN TableB B ON A.CUST_NO = B.InvolvedPartyId_Numeric_ID
),
-- Get the lowest two scores for each customer
TopTwoScores AS (
SELECT
CUST_NO,
Product,
Score
FROM (
SELECT
CUST_NO,
'ca_enpv' AS Product, ca_enpv AS Score FROM FilteredScores
UNION ALL
SELECT
CUST_NO,
'cc_enpv' AS Product, cc_enpv AS Score FROM FilteredScores
UNION ALL
SELECT
CUST_NO,
'hi_enpv' AS Product, hi_enpv AS Score FROM FilteredScores
UNION ALL
SELECT
CUST_NO,
'in_enpv' AS Product, in_enpv AS Score FROM FilteredScores
UNION ALL
SELECT
CUST_NO,
'mg_enpv' AS Product, mg_enpv AS Score FROM FilteredScores
UNION ALL
SELECT
CUST_NO,
'pl_enpv' AS Product, pl_enpv AS Score FROM FilteredScores
UNION ALL
SELECT
CUST_NO,
'pr_enpv' AS Product, pr_enpv AS Score FROM FilteredScores
UNION ALL
SELECT
CUST_NO,
'sv_enpv' AS Product, sv_enpv AS Score FROM FilteredScores
) AS AllScores
WHERE Score > 0 -- Only consider positive scores
),
Ranked AS (
SELECT
CUST_NO,
Product,
Score,
ROW_NUMBER() OVER (PARTITION BY CUST_NO ORDER BY Score ASC) AS rank
FROM TopTwoScores
)
-- Select the lowest two scores for each customer
SELECT
CUST_NO,
Product,
Score
FROM Ranked
WHERE rank <= 2
ORDER BY CUST_NO, rank;
Explaining Steps:
1> FilteredScores: This step computes the score for each product and handles eligibility in one go by multiplying the score with the eligibility flag. Using COALESCE(NULLIF(...)) ensures that only eligible products have non-zero scores.
2> TopTwoScores: This step unpivots the scores into a single column for easier sorting and filtering.
3> Ranked: This step ranks the products for each customer based on the score.
4> Final Selection: This query retrieves the top 2 scores for each customer.