Hi,
I need to calculate the backlog from a table:
components(ProductId, ComponentId, Status, StatusDate)
where ComponentId, Status and StatusDate are the primary key. ProductId is a foreign key. Example:
prod1, comp1, 01, 05/01/2009
prod1, comp1, 02, 05/01/2009
prod1, comp1, 03, 06/01/2009
prod1, comp1, 01, 07/01/2009
prod1, comp1, 02, 20/01/2009
prod2, comp2, 01, 22/01/2009
prod1, comp1, 02, 23/01/2009
prod1, comp1, 03, 31/01/2009
Basically what I am trying to calculate is the number of Components per week in status lower than 03. End user will introduce an interval date so I need to show all the weeks in the interval even if there is not backlog for a week. Expected result when end user introduces 01/01/2009-22/01/2009:
Week, Backlog
1,NULL/0
2,1
3,1
4,2
Explanation for Week 2: comp1 reach status 03 in the week but then goes back to status 01
Any help is more than welcome, thanks
-
This is a partial answer in that I do not see where week 3 (11-18 Jan 2009) is coming from in your example. It illustrates the use of a counter table to get a line for missing values.
SELECT Counter,WeekNo, CountofStatus FROM Counter LEFT JOIN (SELECT Format([StatusDate],"ww") AS WeekNo, COUNT(c.Status) AS CountOfStatus FROM components c WHERE c.StatusDate BETWEEN #1/1/2009# AND #1/22/2009# AND c.Status<3 GROUP BY Format([StatusDate],"ww")) Comp ON Val(Comp.Weekno)=Counter.Counter WHERE Counter.Counter>=Val(Format(#1/1/2009#,"ww")) AND Counter.Counter<=Val(Format( #1/22/2009#,"ww"))
Remou : So the status is continuous and only marked at date changed? If so, my example does not suit.Remou : Your example shows two components, do you have a set number of components and is it large? -
I'm guessing a bit as to what you're trying to do, but here's my best guess:
First, you should have a calendar table in your database:
CREATE TABLE Calendar ( calendar_date DATETIME NOT NULL, week_number INT NOT NULL, CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED (calendar_date) ) GO INSERT INTO Calendar (calendar_date, week_number) VALUES ('1/1/2009', 1) INSERT INTO Calendar (calendar_date, week_number) VALUES ('2/1/2009', 2) etc.
You can add additional columns to the table based on your business needs. For example, an "is_holiday" bit column to track whether or not your office is closed that day. This table makes so many different queries trivial.
Now for your problem:
SELECT CAL.week_number, COUNT(DISTINCT C.component_id) FROM Calendar CAL LEFT OUTER JOIN Components C ON C.status_date = CAL.calendar_date AND C.status IN ('01', '02') WHERE CAL.calendar_date BETWEEN @start_date AND @end_date GROUP BY CAL.week_number
I used the IN for the status since you're using strings, so "< '03'" might not always give you what you want. Is '1' less than '03' in your mind?
Also, if there is a time component on any of your dates the equality and BETWEEN checks might need to be tweaked.
EDIT: I just saw the comments on the other answer. If you are dealing with just status changes, then the following query should work, although there may be a more performant method:
SELECT CAL.week_number, COUNT(DISTINCT C.component_id) FROM Calendar CAL LEFT OUTER JOIN Components C ON C.status_date <= CAL.calendar_date AND C.status IN ('01', '02') LEFT OUTER JOIN Components C2 ON C2.component_id = C.component_id AND C2.status_date > C.status_date AND C2.status_date <= CAL.calendar_date WHERE CAL.calendar_date BETWEEN @start_date AND @end_date AND C2.component_id IS NULL GROUP BY CAL.week_number
I'm not sure where the product fits in with all of this though.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.