Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Generieren Sie eine Zeile pro Minute des Tages aus einer spärlich gefüllten Datenbanktabelle

Stellen Sie sicher, dass die Datumsspalte einen Index hat und die Leistung angemessen sein sollte.

SELECT t.Date,
COUNT(*) AS Quantity,
(SELECT COUNT(*) FROM Table WHERE Date < t.Date) AS RunningTotal
FROM Table t
GROUP BY t.Date

Eine Tabelle, die mit einer Zeile pro Minute gefüllt wird, kann wie folgt extrem schnell erstellt werden:

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);

Vorausgesetzt, Sie benötigen aufgrund von Rekursionsbeschränkungen nur Daten im Wert von <~22 Tagen.

Alles, was Sie jetzt brauchen, ist, die beiden zusammenzuführen, die Verwendung einer temporären Tabelle zum Speichern von Daten scheint am schnellsten zu sein

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