Reputation: 8865
I have sample data set like this :
CREATE TABLE Data
(
Start DATETIME,
EndDt DATETIME,
Amount INT
)
GO
--Insert Data
INSERT INTO Data(Start,EndDt,Amount)
VALUES
('14-Apr-14','13-May-14',200),
('15-May-14','16-Jun-14',320)
Sample Input :
Start End Amount
14-Apr-14 13-May-14 200
15-May-14 16-Jun-14 320
Sample Output :
Start End Amount
14-Apr-14 30-Apr-14 100
01-May-14 13-May-14 100
15-May-14 31-May-14 160
01-Jun-14 16-Jun-14 160
can anyone suggest on this?
Upvotes: 1
Views: 689
Reputation: 95827
This solution works, but assumes you have an ID column on your table. I create a Tally table to be able to generate the date ranges (which in in sets of 16 days, not 15), and then finally get a count in the group and divide Amount
by it:
CREATE TABLE dbo.[Data] (ID int IDENTITY,
[Start] date,
EndDt date,
Amount int);
GO
INSERT INTO dbo.[Data] ([Start],
EndDt,
Amount)
VALUES ('14-Apr-14', '13-May-14', 200),
('15-May-14', '16-Jun-14', 320);
GO
--Create a Tally
WITH N AS
(SELECT N
FROM (VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N (N) ),
Tally AS
(SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1,
N N2,
N N3), --1000 rows, more than enough
--Create the dates
Dates AS(
SELECT D.ID,
DATEADD(DAY, (T.I - 1) * 16, D.[Start]) AS [Start],
DATEADD(DAY, T.I * 16, D.[Start]) AS Enddt,
D.EndDt AS FinalDate,
D.Amount
FROM dbo.[Data] D
CROSS JOIN Tally T
WHERE DATEADD(DAY, (T.I - 1) * 16, D.[Start]) < D.EndDt)
--Final result set
SELECT D.ID,
LAG(DATEADD(DAY,1,D.Enddt),1,D.[Start]) OVER (PARTITION BY D.ID ORDER BY D.[Start]) AS [Start],
CASE WHEN D.Enddt > D.FinalDate THEN D.FinalDate ELSE D.Enddt END AS EndDt,
D.Amount / COUNT(ID) OVER (PARTITION BY ID) AS Amount
FROM Dates D
ORDER BY ID, [Start];
Upvotes: 2
Reputation: 104
Try this. I have tried this code on your table and it is giving desired output
select start as dd,'start' as type,amount/2 as amount from data
union all
select enddt as dd,'end' as type,amount/2 as amount from data
select case when type = 'start' then dd--DATEADD(mm, DATEDIFF(mm, 0, dd), 0)
else DATEADD(mm, DATEDIFF(mm, 0, dd), 0) end
as start,case when type = 'start' then DATEADD (dd, -1, DATEADD(mm, DATEDIFF(mm, 0, dd) + 1, 0))
else dd end as [end],amount
from (select start as dd,'start' as type,amount/2 as amount from data
union all
select enddt as dd,'end' as type,amount/2 as amount from data) a
Upvotes: 0
Reputation: 147
You can use this query:
select Start a, last_day(Start) b, amount/2 c from Data
union
select trunc(EndDt , 'MM') a, EndDt b, amount/2 c from Data;
Upvotes: -1