I have the following results across a table, and what I need to get is the Frequency column down onto the appropriate rows, so the NULL values in the Frequency column are replaced with the appropriate value. Noting the CustomerCode different values.
Anyone know how this could be done, and in doing so removing the Frequency row that doesn't have the Type and TypeAmount?
CustomerCode Frequency Type TypeAmount
C12345 Monthly NULL NULL
C12345 NULL A1 5.00
C12345 NULL A2 20.00
C12345 Fortnightly NULL NULL
C12345 NULL A1 5.00
C12345 NULL A2 20.00
C56789 Fortnightly NULL NULL
C56789 NULL A1 50.00
Desired Output
CustomerCode Frequency Type TypeAmount
C12345 Monthly A1 5.00
C12345 Monthly A2 20.00
C12345 Fortnightly A1 5.00
C12345 Fortnightly A2 20.00
C56789 Fortnightly A1 50.00
Sample Data
Create Table #Data
(
CustomerCode varchar(50),
Frequency varchar(50) NULL,
Type varchar(50) NULL,
TypeAmount money NULL
)
insert into #Data
(
CustomerCode,
Frequency,
Type,
TypeAmount
)
select
'C12345',
'Monthly',
NULL,
NULL
union all
select
'C12345',
NULL,
'A1',
'5.00'
union all
select
'C12345',
NULL,
'A2',
'20.00'
union all
select
'C12345',
'Fornightly',
NULL,
NULL
union all
select
'C12345',
NULL,
'A1',
'5.00'
union all
select
'C12345',
NULL,
'A2',
'20.00'
union all
select
'C56789',
'Fornightly',
NULL,
NULL
union all
select
'C56789',
NULL,
'A1',
'50.00'
select * from #Data
There must be some defined order to your data or else you cannot perform this query. I created an order by inserting your data into a temp table with an identity column for your reference. I'm assuming there is some underlying order defined in your source data. Just swap that out with my surrogate key column [ID]
DROP TABLE IF EXISTS #Data
Create Table #Data
(
ID int Identity(1,1),
CustomerCode varchar(50),
Frequency varchar(50) NULL,
Type varchar(50) NULL,
TypeAmount money NULL
)
INSERT INTO #Data (CustomerCode,Frequency,[Type],TypeAmount )
VALUES ('C12345','Monthly',NULL,NULL)
,('C12345',NULL,'A1','5.00')
,('C12345',NULL,'A2','20.00')
,('C12345','Fornightly',NULL,NULL)
,('C12345',NULL,'A1','5.00')
,('C12345',NULL,'A2','20.00')
,('C56789','Fornightly',NULL,NULL)
,('C56789',NULL,'A1','50.00')
Select *
FROM #Data
SELECT A.ID
,B.Frequency
,A.Type
,A.TypeAmount
from #Data as A
Cross Apply
( /*Grab most recent preceding row that has frequency populated*/
SELECT Top (1) DTA.Frequency
From #Data AS DTA
Where A.CustomerCode = DTA.CustomerCode
AND DTA.ID < A.ID
AND DTA.Frequency IS NOT NULL
Order by DTA.ID DESC
) AS B
WHERE A.Frequency IS NULL
If performance is an issue, recommend creating an index like so before executing your select:
Create Index ix on #Data(CustomerCode,ID) Include (Frequency)