Reputation: 375
I have a table like such:
LeaveRequestID | DateAllocated | DateFrom | DateTo | TotalLeaveDays
1 | 2020-03-02 | 2020-03-02 | 2020-03-05 | 3
2 | 2020-03-02 | 2020-03-02 | 2020-03-04 | 2
And here's my query:
SELECT
t1.DateAllocated,
t2.DateFrom,
t2.DateTo,
DATEDIFF(DAY, t2.DateFrom, t2.DateTo) TotalLeaveDays
FROM
tblLeave_Allocation t1
INNER JOIN
tblLeave_Requests t2 ON CONVERT(VARCHAR, t1.DateAllocated, 23) = CONVERT(VARCHAR, t2.DateFrom, 23)
Here is my desired output:
LeaveRequestID | DateAllocated | DateFrom | DateTo | TotalLeaveDays | DateDist | LeaveCount
1 | 2020-03-02 | 2020-03-02 | 2020-03-05 | 3 | 2020-03-03 | 1
1 | 2020-03-02 | 2020-03-02 | 2020-03-05 | 3 | 2020-03-04 | 1
1 | 2020-03-02 | 2020-03-02 | 2020-03-05 | 3 | 2020-03-05 | 1
2 | 2020-03-02 | 2020-03-02 | 2020-03-04 | 2 | 2020-03-03 | 1
2 | 2020-03-02 | 2020-03-02 | 2020-03-04 | 2 | 2020-03-04 | 1
I would like to distribute every count of single TotalLeaveDays
for each count starting from a day after DateFrom
until DateTo
. How to achieve my desired output?
Upvotes: 0
Views: 60
Reputation: 81970
Here is another option which uses an ad-hoc tally/numbers table
Example
Select A.*
,DateDist = dateadd(DAY,N,DateFrom)
From YourTable A
Join (
Select Top 10000 N=Row_Number() Over (Order By (Select NULL))
From master..spt_values n1, master..spt_values n2
) B on N<=TotalLeaveDays
Order By LeaveRequestID,N
Returns
LeaveRequestID DateAllocated DateFrom DateTo TotalLeaveDays DateDist
1 2020-03-02 2020-03-02 2020-03-05 3 2020-03-03
1 2020-03-02 2020-03-02 2020-03-05 3 2020-03-04
1 2020-03-02 2020-03-02 2020-03-05 3 2020-03-05
2 2020-03-02 2020-03-02 2020-03-04 2 2020-03-03
2 2020-03-02 2020-03-02 2020-03-04 2 2020-03-04
Upvotes: 0
Reputation: 1269953
A recursive CTE seems well suited for this:
with cte as (
select LeaveRequestID, DateAllocated, DateFrom, DateTo, TotalLeaveDays,
1 as n, dateadd(day, 1, datefrom) as datedist
from t
union all
select LeaveRequestID, DateAllocated, DateFrom, DateTo, TotalLeaveDays,
n + 1, dateadd(day, 1, datedist) as datedist
from cte
where n < TotalLeaveDays
)
select LeaveRequestID, DateAllocated, DateFrom, DateTo, TotalLeaveDays, datedist, 1
from cte;
Upvotes: 1
Reputation: 2584
You can do this by creating/using a calendar table and then joining it to our current result. In SQL Server, you can use the following steps:
Creating the calendar table (If you already don't have one):
DECLARE @MinDate DATE = '20200101',
@MaxDate DATE = '20210101';
SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)
INTO #Calendar
FROM sys.all_objects a
CROSS JOIN sys.all_objects b;
Creating Sample Current Output:
select a.*
into #tableA
from
(select 1 as LeaveRequestID,CAST('2020-03-02' as date) as DateAllocated,
CAST('2020-03-02' as date) as DateFrom,CAST('2020-03-05' as date) as DateTo,
3 as TotalLeaveDays union
select 2 as LeaveRequestID,CAST('2020-03-02' as date) as DateAllocated,
CAST('2020-03-02' as date) as DateFrom,CAST('2020-03-04' as date) as DateTo,
2 as TotalLeaveDays) a
Performing the join to get the desired output:
select a.*,
b.[date] as DateDist
from #tableA a
left join #Calendar b
on b.[date] between DATEADD(d,1,a.Datefrom) and a.DateTo
Hope this helps.
Upvotes: 1