Jestem bardzo spóźniony na imprezę, ale to nie pojawia się w żadnej z istniejących odpowiedzi:
GROUP BY DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', date_column) / 10 * 10, '2000')
- Te
10
i MINUTE
terminy mogą zostać zmienione na dowolną liczbę iDATEPART
odpowiednio.
- To jest
DATETIME
wartość, która oznacza:
- Działa dobrze w długich odstępach czasu. (Nie ma kolizji między latami.)
- Włączenie go do
SELECT
instrukcji da wynikowi kolumnę z ładnymi danymi wyjściowymi obciętymi na określonym poziomie.
'2000'
to „data zakotwiczenia”, wokół której SQL wykona obliczenia związane z datą. Jereonh odkrył poniżej, że przy poprzedniej funkcji anchor ( 0
) napotykasz przepełnienie liczb całkowitych, gdy grupujesz ostatnie daty według sekund lub milisekund. †
SELECT DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', aa.[date]) / 10 * 10, '2000')
AS [date_truncated],
COUNT(*) AS [records_in_interval],
AVG(aa.[value]) AS [average_value]
FROM [friib].[dbo].[archive_analog] AS aa
GROUP BY DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', aa.[date]) / 10 * 10, '2000')
ORDER BY [date_truncated]
Jeśli Twoje dane obejmują stulecia, ‡ używanie pojedynczej daty zakotwiczenia dla grupowania w sekundach lub milisekundach nadal spowoduje przepełnienie. Jeśli tak się dzieje, możesz poprosić każdy wiersz o zakotwiczenie porównania kategoryzacji do północy jego własnej daty:
Użyj DATEADD(DAY, DATEDIFF(DAY, 0, aa.[date]), 0)
zamiast tego, '2000'
gdzie pojawia się powyżej. Twoje zapytanie będzie całkowicie nieczytelne, ale zadziała.
Alternatywą może być CONVERT(DATETIME, CONVERT(DATE, aa.[date]))
zamiana.
† 2 32 ≈ 4,29E + 9, więc jeśli tak DATEPART
jest SECOND
, zyskujesz 4,3 miliarda sekund w każdą stronę, czyli „kotwicę ± 136 lat”. Podobnie, 2 32 milisekundy to ≈ 49,7 dnia.
‡ Jeśli Twoje dane obejmują stulecia lub milenia i nadal są dokładne z dokładnością do sekundy lub milisekundy… gratulacje! Cokolwiek robisz, rób to dalej.
ROUND((DATEPART(MINUTE, DT.[Date]) / 5),0,1) * 5
tak, że kiedy patrzę na dane, jest to skorelowane z najbliższym przedziałem czasowym