I use something like this to generate dates:
Declare @minDate date = '2018-03-01'
, @maxDate date = '2018-03-06';
With dates
As (
Select n.id
, DateValue = dateadd(day, n.id, @minDate)
From (Select row_number() over(Order By ac.object_id) - 1 As id
From sys.all_columns ac) As n
)
Select *
From dates d
Where d.DateValue <= @maxDate;
Now - you just need to get the row that applies for that date - and to do that we can use a CROSS APPLY:
Declare @product Table (
Product char(1)
, Location tinyint
, TransDate DATE
, TransBal int
);
Insert @product (
Product
, Location
, TransDate
, TransBal
)
Values ('A', 1, '02/01/2018', 50)
, ('A', 1, '02/15/2018', 75)
, ('A', 2, '03/01/2018', 25)
, ('A', 2, '03/06/2018', 50)
, ('B', 1, '03/01/2018', 25);
Select * From @product;
Declare @minDate date = (Select min(p.TransDate) From @product p)
, @maxDate date = (Select max(p.TransDate) From @product p);
With dates
As (
Select n.id
, DateValue = dateadd(day, n.id, @minDate)
From (Select row_number() over(Order By ac.object_id) - 1 As id
From sys.all_columns ac) As n
)
Select pd.Product
, pd.Location
, d.DateValue As TransDate
, pd.TransBal
From dates d
Cross Apply (Select Top 1
*
From @product p
Where p.TransDate <= d.DateValue
Order By
p.TransDate desc) As pd
Where d.DateValue <= @maxDate;
If you already have a number or tally table - you can replace the derived table with the row_number function and use your number or tally table directly.
Edit: I missed part of the relationship in the cross apply - if multiple products can have the same transdate then you need to include that. To do that you would change the query to:
With dates
As (
Select n.id
, DateValue = dateadd(day, n.id, @minDate)
From (Select row_number() over(Order By ac.object_id) - 1 As id
From sys.all_columns ac) As n
)
Select Distinct pd.Product
, pd.Location
, d.DateValue As TransDate
, pd.TransBal
From dates d
Cross Join @product p
Cross Apply (Select Top 1
*
From @product p1
Where p1.Product = p.Product And p1.TransDate <= d.DateValue
Order By
p1.TransDate desc) As pd
Where d.DateValue <= @maxDate;
The CROSS JOIN creates a row for each date - the WHERE in the CROSS APPLY then limits the value to the preceding product value - and the DISTINCT eliminates any duplicates generated by the cross join.
Jeffrey Williams
“We are all faced with a series of great opportunities brilliantly disguised as impossible situations.”
― Charles R. Swindoll
How to post questions to get better answers faster
Managing Transaction Logs