2016-06-06 13 views
1

Um Daten für einige Berichte zu erhalten, muss ich wissen, wie viele Zeilen pro Stunde in einer Tabelle ab einer bestimmten Stunde für einen bestimmten Tag eingefügt wurden. Ich habe bereits einen Teil der Lösung in another question gefunden, aber es ist mir nicht gelungen, einen Weg zu finden, ihn in meinem Fall anzupassen. Dies ist der Code, den ich bisher geschrieben habe:Anzahl der Zeilen pro Stunde ab einer bestimmten Zeit

SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, t.mydatetime), 0) AS HOUR_CONCERNED, 
     COUNT(*) AS NB_ROWS 
FROM mytable t 
WHERE CONVERT(DATETIME, FLOOR(CONVERT(FLOAT, t.mydatetime))) = '2016-06-06' 
GROUP BY DATEADD(HOUR, DATEDIFF(HOUR, 0, t.mydatetime), 0) 
ORDER BY HOUR_CONCERNED; 

Es gibt mir die folgenden Ergebnisse:

HOUR_CONCERNED   NB_ROWS 
-------------------  -------- 
2016-06-06 10:00:00  2157 
2016-06-06 11:00:00  60740 
2016-06-06 12:00:00  66189 
2016-06-06 13:00:00  77096 
2016-06-06 14:00:00  90039 

Das Problem ist, dass ich nicht einen Weg finden, meine Ergebnisse zu einem bestimmten starten Zeit wie 9.30 Uhr und um die Anzahl der Zeilen pro Stunde ab dieser Zeit zu bekommen. Mit anderen Worten, ich bin auf der Suche nach der Anzahl der Zeilen von 09.30 Uhr bis 10.30 Uhr, 10.30 Uhr bis 11.30 Uhr, usw. Die Ergebnisse, die ich suche sollen wie folgt aussehen:

HOUR_CONCERNED   NB_ROWS 
-------------------  -------- 
2016-06-06 09:30:00  3550 
2016-06-06 10:30:00  33002 
2016-06-06 11:30:00  42058 
2016-06-06 12:30:00  55008 
2016-06-06 13:30:00  72000 

Gibt es eine einfache Möglichkeit, meine Abfrage anzupassen und diese Ergebnisse zu erhalten?

Antwort

2

eine bestimmte Startzeit gegeben, können Sie Stunde Blöcke erhalten, indem die Anzahl der Minuten seit der Startzeit zu finden, und dividiert durch 60, dann diese Anzahl von Stunden zurück zu der Startzeit hinzufügen, z

DECLARE @StartTime DATETIME2(0) = '20160606 09:30'; 
WITH DummyData (mydatetime) AS 
( SELECT TOP 200 DATEADD(MINUTE, ROW_NUMBER() OVER(ORDER BY [object_id]) - 1, @StartTime) 
    FROM sys.all_objects 
) 
SELECT HoursSinceStart = FLOOR(DATEDIFF(MINUTE, @StartTime, mydatetime)/60.0), 
     Display = DATEADD(HOUR, FLOOR(DATEDIFF(MINUTE, @StartTime, mydatetime)/60.0), @StartTime), 
     Records = COUNT(*) 
FROM DummyData 
WHERE myDateTime >= @StartTime 
GROUP BY FLOOR(DATEDIFF(MINUTE, @StartTime, mydatetime)/60.0) 
ORDER BY Display; 

Welche gibt:

HoursSinceStart  Display     Records 
0     2016-06-06 09:30:00  60 
1     2016-06-06 10:30:00  40 
2     2016-06-06 11:30:00  60 
3     2016-06-06 12:30:00  20 

ich die HoursSinceStart Spalte, hoffentlich verlassen haben, in dekonstruiert die Logik in der Display

mit dieser Methode

Das Problem Spalte enthalten sind, zu unterstützen, ist, dass es geben Sie nur Ergebnisse für Blöcke, die vorhanden sind, wenn Sie auch diejenigen benötigen, die nicht alle Zeitblöcke mit einer Zahlentabelle generieren müssen, dann linken Sie zu Ihren Daten:

Sie können eine Reihe von Zahlen mit diesem schnell erzeugen:

DECLARE @StartTime DATETIME2(0) = '20160606 09:30'; 

-- GENERATE 10 ROWS 
WITH N1 AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)), 

-- CROSS JOIN THE 10 ROWS TO GET 100 ROWS 
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2), 

--CROSS JOIN THE 100 ROWS TO GET 10,000 ROWS 
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2), 

--APPLY ROW_NUMBER TO GET A SET OF NUMBERS FROM 0 - 99,999 
Numbers (N) AS (SELECT ROW_NUMBER() OVER(ORDER BY N) - 1 FROM N3) 

SELECT *, 
     TimeStart = DATEADD(HOUR, N, @StartTime), 
     TimeEnd = DATEADD(HOUR, N + 1, @StartTime) 
FROM Numbers; 

die so etwas wie gibt:

N TimeStart    TimeEnd 
-------------------------------------------------- 
0 2016-06-06 09:30:00  2016-06-06 10:30:00 
1 2016-06-06 10:30:00  2016-06-06 11:30:00 
2 2016-06-06 11:30:00  2016-06-06 12:30:00 
3 2016-06-06 12:30:00  2016-06-06 13:30:00 
4 2016-06-06 13:30:00  2016-06-06 14:30:00 
5 2016-06-06 14:30:00  2016-06-06 15:30:00 
6 2016-06-06 15:30:00  2016-06-06 16:30:00 
7 2016-06-06 16:30:00  2016-06-06 17:30:00 

Dann Sie Ihre Daten auf diese verbinden links können (Sie werden wahrscheinlich auch eine Endzeit brauchen);

DECLARE @StartTime DATETIME2(0) = '20160606 09:30', 
     @EndTime DATETIME2(0) = '20160606 15:30'; 

WITH DummyData (mydatetime) AS 
( SELECT TOP 200 DATEADD(MINUTE, ROW_NUMBER() OVER(ORDER BY [object_id]) - 1, @StartTime) 
    FROM sys.all_objects 
), 
-- GENERATE NUMBERS 
N1 AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)), 
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2), 
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2), 
Numbers (N) AS (SELECT ROW_NUMBER() OVER(ORDER BY N) - 1 FROM N3), 

TimePeriods AS 
( SELECT TimeStart = DATEADD(HOUR, N, @StartTime), 
      TimeEnd = DATEADD(HOUR, N + 1, @StartTime) 
    FROM Numbers 
    WHERE DATEADD(HOUR, N, @StartTime) < @EndTime 
) 

SELECT tp.TimeStart, tp.TimeEnd, Records = COUNT(dd.myDateTime) 
FROM TimePeriods AS tp 
     LEFT JOIN DummyData AS dd 
      ON dd.mydatetime >= tp.TimeStart 
      AND dd.mydatetime < tp.TimeEnd 
GROUP BY tp.TimeStart, tp.TimeEnd 
ORDER BY tp.TimeStart; 

Welche 0 zurück, wo es keine Datensätze:

TimeStart    TimeEnd     Records 
--------------------------------------------------------- 
2016-06-06 09:30:00  2016-06-06 10:30:00  60 
2016-06-06 10:30:00  2016-06-06 11:30:00  60 
2016-06-06 11:30:00  2016-06-06 12:30:00  60 
2016-06-06 12:30:00  2016-06-06 13:30:00  20 
2016-06-06 13:30:00  2016-06-06 14:30:00  0 
2016-06-06 14:30:00  2016-06-06 15:30:00  0 
+0

Vielen Dank für Ihre Antwort. Ich brauchte einige Zeit, um zu verstehen, wie ich es mit meinen Daten verwenden kann, aber es funktioniert jetzt gut. :) – Aleph0

0

Sie müssen die Zeit in der WHERE-Klausel haben, und legen Sie eine größere als gegen die Zeit, aus der Sie messen möchten? Sie können auch DATEPART verwenden, um die Stunden zu erhalten.

 SELECT NB_ROWS = COUNT(*) 
       ,HOUR_CONCERNED = DATEPART(HOUR, InsertedDate) 
     FROM table 
     WHERE InsertedDate = '20160531' 
     AND InsertedDate> time 
     GROUP BY DATEPART(HOUR, InsertedDate) 
+0

Dank für Ihre Antwort danken, aber ich glaube nicht, das gibt mir die erwarteten Ergebnisse. Ich denke, Ihre Abfrage gibt mir die Anzahl der Zeilen zwischen 9.30 Uhr und 10.00 Uhr, zwischen 10.00 Uhr und 11.00 Uhr usw. Ich suche nach der Anzahl der Zeilen zwischen 9.30 Uhr und 10.30 Uhr, zwischen 10.30 Uhr und 11.30 Uhr usw Bin ich falsch über die Ergebnisse, die ich bekomme? – Aleph0

+0

Ich habe meine Frage bearbeitet, um zu verdeutlichen, welche Ergebnisse ich erzielen möchte. – Aleph0

1

Diese Versuchen:

SELECT DATEADD(MINUTE, 30, DATEADD(HOUR, DATEDIFF(HOUR, 0, DATEADD(MINUTE, -30, t.mydatetime)), 0)) AS HOUR_CONCERNED, 
     COUNT(*) AS NB_ROWS 
FROM mytable t 
WHERE CONVERT(DATETIME, FLOOR(CONVERT(FLOAT, t.mydatetime))) = '2016-06-06' 
GROUP BY DATEADD(HOUR, DATEDIFF(HOUR, 0, DATEADD(MINUTE, -30, t.mydatetime)), 0) 
ORDER BY HOUR_CONCERNED; 

I gegeben, um eine 30 min in die GROUP BY-Funktion versetzt 09.30 als 9:00 bis zu behandeln, 10.30 als 10:00 Uhr und so weiter. Im Auswahlteil kehre ich diesen Offset um, um ein passendes Intervall zu erhalten.

Die WHERE-Bedingung in Ihrer Abfrage muss aus Leistungsgründen geändert werden. Statt Zeitstempel auf einen nächsten Tag Kürzen, sollen Sie von einem Bereich filtern:

WHERE t.mydatetime >= CONVERT(DATETIME, '2016-06-06') AND t.mydatetime < CONVERT(DATETIME, '2016-06-07') 
+0

Danke, es gibt mir die erwarteten Ergebnisse. Ich nehme die Antwort von @ GarethD an, weil sie vollständiger ist und gebe mir auch '0', wenn es eine Stunde lang keine Zeile gibt. +1 auf jeden Fall :) – Aleph0

Verwandte Themen