Dominic
Here's another way of doing it. It avoids the correlated subquery in David's solution and so it may perform better. You'll want to test.
John
-- Data
WITH MyCTE(ClaimKey ,ARevDate ,ARowNum,CauseCode) AS (
SELECT 123456789,20120101 ,1,'Fault'
UNION select 123456789,20120201, 2,NULL
UNION select 123456789,20120301 ,3,NULL
UNION select 123456789,20120401 ,4,NULL
UNION select 123456789,20120501 ,5,'Non-Fault'
UNION select 123456789,20120601 ,6,NULL
UNION select 123456789,20120701 ,7,NULL
UNION select 123456789,20120701 ,8,NULL
UNION SELECT 123456789,20120701 ,9,'Fault'
UNION select 123456789,20120701 ,10,NULL
UNION SELECT 123456789,20120701 ,11,'fault'
UNION SELECT 123456789,20120701 ,12,'non fault'
UNION select 123456789,20120701 ,13,NULL
UNION select 123456789,20120701 ,14,NULL
)
-- Number the rows where a code is specified so we can see where it changes
, Numbered (ClaimKey, ARevDate, ARowNum, CauseCode, RowNo) AS (
SELECT ClaimKey, ARevDate, ARowNum, CauseCode,
ROW_NUMBER() OVER (ORDER BY ARowNum)
FROM MyCTE
WHERE CauseCode IS NOT NULL
)
-- Self-join to get ranges with the same code
, ShowNext (ClaimKey, ARevDate, ARowNum, CauseCode, NextRowNum) AS (
SELECT n1.ClaimKey, n1.ARevDate, n1.ARowNum, n1.CauseCode,
COALESCE(n2.ARowNum, (SELECT MAX(ARowNum)+1 FROM MyCTE)) -- add 1 to the highest value for the final number in the range
FROM Numbered n1
LEFT JOIN Numbered n2 -- need LEFT JOIN to capture the final value
ON n1.RowNo = n2.RowNo - 1
)
SELECT m.ClaimKey, m.ARevDate, m.ARowNum,
COALESCE(s.CauseCode,m.CauseCode) CauseCode
FROM MyCTE m
LEFT JOIN ShowNext s
ON m.ARowNum BETWEEN s.ARowNum + 1 AND s.NextRowNum - 1