I have a table populated with time stamped rows inserted at (essentially) random point in the day.
I need to generate running totals with 1 row per minute (so for a
Make sure the date column has an index on it and performance should be reasonable.
SELECT t.Date,
COUNT(*) AS Quantity,
(SELECT COUNT(*) FROM Table WHERE Date < t.Date) AS RunningTotal
FROM Table t
GROUP BY t.Date
Getting a table populated with one row per minute can be done extremely quickly as follows:
DECLARE @StartDate smalldatetime
DECLARE @EndDate smalldatetime
SET @StartDate = '1 jan 2009' --MIN(TimeStamp) FROM Table
SET @EndDate = '2 jan 2009' --MAX(TimeStamp) FROM Table
SET @StartDate = DATEADD(minute,-DATEPART(minute,@StartDate),@StartDate)
SET @EndDate = DATEADD(minute,-DATEPART(minute,@EndDate),@EndDate)
; WITH DateIntervalsCTE AS
(
SELECT 0 i, @startdate AS Date
UNION ALL
SELECT i + 1, DATEADD(minute, i, @startdate )
FROM DateIntervalsCTE
WHERE DATEADD(minute, i, @startdate ) <= @enddate
)
SELECT DISTINCT Date FROM DateIntervalsCTE
OPTION (MAXRECURSION 32767);
Provided you only need < ~22 days worth of data due to recursion restrictions.
All you need now is to merge the two, using a temp table to hold data seems to be quickest
DECLARE @StartDate smalldatetime
DECLARE @EndDate smalldatetime
DECLARE @t TABLE (Date smalldatetime,Quantity int,RunningTotal int)
SET @StartDate = '1 jan 2009' --MIN(TimeStamp) FROM Table
SET @EndDate = '2 jan 2009' --MAX(TimeStamp) FROM Table
SET @StartDate = DATEADD(minute,-DATEPART(minute,@StartDate),@StartDate)
SET @EndDate = DATEADD(minute,-DATEPART(minute,@EndDate),@EndDate)
; WITH DateIntervalsCTE AS
(
SELECT 0 i, @startdate AS Date
UNION ALL
SELECT i + 1, DATEADD(minute, i, @startdate )
FROM DateIntervalsCTE
WHERE DATEADD(minute, i, @startdate ) <= @enddate
)
INSERT INTO @t (Date)
SELECT DISTINCT Date FROM DateIntervalsCTE
OPTION (MAXRECURSION 32767);
UPDATE t SET Quantity = (SELECT COUNT(d.TimeStamp) FROM Table d WHERE Date = t.date)
from @t t
update t2 set runningtotal = (SELECT SUM(Quantity) FROM @t WHERE date <= t2.date)
from @t t2
select * from @t
You'll want to use group by for sure. The hard(ish) part is that it'll be synthetic, meaning you'll have to create it yourself. There are a bunch of ways to do that
GROUP BY year(yourdate), month(yourdate), day(yourdate) etc...
Except I can't remember if there are hours() and minutes() functions off the top of my head.
You can also use the datepart function.
Then you can put those all together in one column for a nice looking label.