I have a set of call detail records, and from those records, I\'m supposed to determine the average concurrent active calls per system, per hour (at a precision of one minute).
My first bit of advice would be, if you ever find yourself saying (when using SQL) "I can create a loop..." then you should immediately start looking for a set-based approach. Get out of the procedural mindset when using SQL.
There are still a few fuzzy parts to your logic. Does a call count as being during a minute period if it simply has any portion of the call during that minute? For example, if a call starts at 1923 and lasts 62 seconds is it considered to overlap with all calls starting at 1924? I'm going to assume yes on that one, but you can adjust the code below if that's not true. It should be a minor tweak.
For the breakdown to minutes I would usually use a table with time spans - a start time and end time for each of the slices in which I'm interested. In your case since you are dealing with exact minutes and your start times are in minutes (even if the data type is screwed up) I'm just going to use a single column with the exact minute in question.
To set up that table:
CREATE TABLE dbo.Minutes (
start_time INT NOT NULL,
CONSTRAINT PK_Minutes PRIMARY KEY CLUSTERED (start_time)
)
DECLARE
@hour TINYINT,
@minute TINYINT
SET @hour = 19
SET @minute = 0
WHILE (@hour <= 20)
BEGIN
INSERT INTO dbo.Minutes (start_time) VALUES (@hour * 100 + @minute)
SET @minute = @minute + 1
IF @minute = 60
BEGIN
SET @minute = 0
SET @hour = @hour + 1
END
END
Now we can select for the averages, etc.
SELECT
M.start_time,
COUNT(R.seconds)
FROM
dbo.Minutes M
LEFT OUTER JOIN dbo.Records R ON
M.start_time BETWEEN CAST(R.time AS INT) AND
(CAST(SUBSTRING(time, 1, 2) AS INT) * 100) + -- hours
(FLOOR((CAST(SUBSTRING(time, 3, 2) AS INT) + FLOOR(dur/60))/60)) + -- carryover to hours
(CAST(SUBSTRING(time, 3, 2) AS INT) + dur/60) % 60 -- minutes
GROUP BY
M.start_time
You'll need to either use that as a subquery to get the averages over a given time. Since it's late on Friday I'll leave that step up to you ;)
EDIT: One last caveat: I didn't account for time spans that cross day boundaries (i.e., go past midnight). Hopefully the code points you in the right direction for that. A better approach might be to create a view that turns all of those nasty strings into actual DATETIME values, then this becomes really trivial with the Minutes table.