Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Tuesday, December 16, 2008 3:08 PM
I am working with a database that stores information using a date range and a value as shown below.
ORIGINAL RECORDS FROM FORECAST Table
FORECASTID ASSINGMENTID STARTDATE ENDDATE FORECASTVALUE
1121 578 10/1/08 12/31/08 0.75
2327 648 11/1/08 12/31/09 0.60
In this example, the FORECAST value is an estimate of the FTE (full time equivalent) headcount that will be needed during that date range. For reporting purposes, it would be much easier if I could expand that single record into a separate record for each month. This would allow me to aggregate the data much more easily than I can now with the way the database is laid out.
The desired state would look like the table shown below..
DESIRED RECORDSET
FORECASTID ASSIGNMENTID FORECASTMONTH FORECASTVALUE
1121 578 10/1/08 0.75
1121 578 11/1/08 0.75
1121 578 12/1/08 0.75
2327 648 11/1/08 0.60
2327 648 12/1/08 0.60
2327 648 01/1/09 0.60
2327 648 02/1/09 0.60
2327 648 03/1/09 0.60
Anybody have any ideas on how to accomplish this?
Tuesday, December 16, 2008 4:22 PM ✅Answered | 3 votes
I agree with Arnie here. A calendar table makes this type of processing very simplistic, performant, and manageable. You can use the code below to get a general idea of how to attack the problem.
DECLARE @t TABLE( |
FORECASTID INT, |
ASSIGNMENTID INT, |
STARTDATE datetime, |
ENDDATE datetime, |
FORECASTVALUE DECIMAL(9,2) |
) |
INSERT INTO @t VALUES (1121,578,'10/1/2008','12/31/2008',0.75); |
INSERT INTO @t VALUES (2327,648,'11/1/2008','3/30/2009',0.60); |
SELECT |
t.Forecastid, |
t.AssignmentID, |
DateAdd(MONTH,DateDiff(MONTH,0,c.dte),0) AS ForecastMonth, |
t.ForecastValue |
FROM [Calendar] c |
LEFT JOIN @t t |
ON c.dte >= t.StartDate AND |
c.dte <= EndDate |
WHERE |
c.[Dte] >= '10/1/2008' AND |
c.[Dte] <= '12/31/2009' AND |
t.ForecastvALUE > 0 |
GROUP BY |
t.Forecastid, |
t.AssignmentID, |
DateAdd(MONTH,DateDiff(MONTH,0,c.dte),0), |
t.ForecastValue |
/* |
FORECASTID ASSIGNMENTID FORECASTMONTH FORECASTVALUE |
1121 578 10/1/08 0.75 |
1121 578 11/1/08 0.75 |
1121 578 12/1/08 0.75 |
2327 648 11/1/08 0.60 |
2327 648 12/1/08 0.60 |
2327 648 01/1/09 0.60 |
2327 648 02/1/09 0.60 |
2327 648 03/1/09 0.60 |
*/ |
Tuesday, December 16, 2008 3:20 PM
The only way i see this possible is to do it with a loop in a transact SQL procedure. Here are the steps i don't know by heart the way to do it so i'll use keywords instead
- Declare and open a cursor on the data to work with
- Loop the cursor and for each record:
- Loop the month difference between the start and enddate using a for loop
- Output the data to the buffer
You can find all the info you need with the keywords CURSOR. I started with that and was able to produce some quite crazy things with this.
Peace man
Groupe-CDGI Developper
Tuesday, December 16, 2008 3:24 PM | 1 vote
This is one of those situations where have a 'Calendar' table in the database makes life simple.
Please review these resources about using a Calendar table.
http://sqlblogcasts.com/blogs/tonyrogerson/archive/2008/01/20/calendar-table-example-and-how-to-use-it.aspx
http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html
You may be only one person in the world, but you may also be the world to one person.
Note: Using a CURSOR is NOT the best solution for this problem.
Tuesday, December 16, 2008 3:49 PM
Wow arnie, this is great, i think i can actually solve my problem in the thread i just posted this morning. If not, i can probably go one step further... I'll stop here, my point is not to hijack this thread. thanks
Groupe-CDGI Developper
Monday, January 5, 2009 6:39 PM
marcjmorris,
Has your issue been resolved? If so, please mark the post(s) that helped you solve your issue, as the answer.
Thanks,
Adam