Generate a row per minute of the day from a sparsely populated database table

前端 未结 2 1302
耶瑟儿~
耶瑟儿~ 2021-01-03 08:41

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

相关标签:
2条回答
  • 2021-01-03 09:25

    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
    
    0 讨论(0)
  • 2021-01-03 09:36

    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.

    0 讨论(0)
提交回复
热议问题