Basado en SQL Fiddle, hice un nuevo intento, que creo que es correcto, aunque devuelve 81 y no 100 para John:
; with LP (CustomerId, Name, UserActions, TotalPoints) as (
SELECT
C.CustomerId,
C.Name,
sum(case when P.LoyaltyPointsId = 4 then isnull(R.RedeemCount, 0) else 1 end),
sum(P.Points * case when P.LoyaltyPointsId = 4 then isnull(R.RedeemAmount,0) else 1 end)
from
CustomerTable C
join LoyaltyDetailsTable D on D.CustomerId = C.CustomerId
join LoyaltyPointTable P on P.LoyaltyPointsId = D.LoyaltyPointsId
outer apply (
select sum(Amount) as RedeemAmount, count(Amount) as RedeemCount
from RedeemPointsTable R
where R.CustomerId = C.CustomerId
) R
group by C.CustomerId, C.Name
),
PP (CustomerId, Pricepoints) as (
select C.CustomerId, sum(P.Pricepoints)
from PriceTable P
join PriceClaimTable C on P.PriceClaimId = C.PriceClaimId
group by C.CustomerId
)
select
LP.CustomerId, LP.Name, LP.UserActions, LP.TotalPoints - isnull(PP.Pricepoints, 0) as Points
from
LP
left outer join PP on LP.CustomerId = PP.CustomerId
order by LP.CustomerId
Se supone que el cliente siempre se encuentra en las tablas de fidelización, pero no necesariamente en las tablas de precios o canje.
SQL Fiddle para esta versión:http://sqlfiddle.com/#!3/5e379/8