I have a table with data like this:
CREATE TABLE Test
(CustName varchar(20), Country varchar(20), RecordedTime datetime, CurrNo tinyint);
INSERT INTO Test
From what I understand from the different scenario's, they can be achieved by basically only 2 rules.
With a few window functions and an OR in the outer query, we can have two rules to target all scenarios.
And then use CASE WHEN
to calculate the "Audit" and the "History".
SELECT
CustName, Country,
FORMAT(RecordedTime, 'yyyy-MMM-dd hh:mm tt') as RecordedTime,
(CASE CurrNo
WHEN 1 then 'ADD'
ELSE 'CHANGE'
END) as [Audit],
(CASE
WHEN CurrNo = 1 then 'NEW'
WHEN ReverseCurrRN = 1 then 'CURRENT'
ELSE 'BEFORE'
END) as [History]
--, CurrNo, ReverseCurrRN, MinCurrNoPerCust, MaxCurrNoPerCustDate ,MinCurrNoPerCust, MinDatePerCust, MaxDatePerCust
FROM
(
SELECT CustName, Country, RecordedTime, CurrNo
,ROW_NUMBER() OVER (PARTITION BY CustName ORDER BY CurrNo DESC) AS ReverseCurrRN
,MIN(CurrNo) OVER (PARTITION BY CustName) AS MinCurrNoPerCust
,MAX(CurrNo) OVER (PARTITION BY CustName, cast(RecordedTime AS DATE)) AS MaxCurrNoPerCustDate
,CAST(MIN(RecordedTime) OVER (PARTITION BY CustName) AS DATE) AS MinDatePerCust
,CAST(MAX(RecordedTime) OVER (PARTITION BY CustName) AS DATE) AS MaxDatePerCust
FROM Test t
WHERE CAST(RecordedTime AS DATE) between DATEADD(day,-1,@Date) and @Date
) q
WHERE MaxDatePerCust = @Date
AND (
-- Scenario 1 & 2 & 4 & 6
(MinDatePerCust = MaxDatePerCust AND (ReverseCurrRN = 1 OR CurrNo = MinCurrNoPerCust OR (MinCurrNoPerCust = 1 AND ReverseCurrRN = 2)))
-- Scenario 2 & 3 & 5 & 7 & 8
OR (MinDatePerCust != MaxDatePerCust AND (ReverseCurrRN = 1 OR CurrNo = 1 OR CurrNo = MaxCurrNoPerCustDate))
)
ORDER BY MinDatePerCust, CustName, CurrNo;
You can test it on db<>fiddle here