Я дуже спізнився на вечірку, але це не відображається в жодній із існуючих відповідей:
GROUP BY DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', date_column) / 10 * 10, '2000')
10
І MINUTE
терміни можуть бути змінені в будь-яке число і DATEPART
, відповідно.
- Це
DATETIME
цінність, яке означає:
- Це прекрасно працює протягом тривалих часових інтервалів. (Між роками немає зіткнення.)
- Якщо включити його у
SELECT
виписку, ви отримаєте ваш стовпець із стовпчиком із сильно врізаним на визначеному вами рівні.
'2000'
- "дата прив'язки", навколо якої SQL виконуватиме математику дат. Нижче Джереон виявив, що ви стикаєтесь із цілим переповненням попереднього якоря ( 0
), коли ви групуєте останні дати за секундами або мілісекундами. †
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]
Якщо ваші дані охоплюють століття, ‡ використання однієї дати прив’язки для групування другої або мілісекундної системи все одно матиме переповнення. Якщо це відбувається, ви можете попросити кожен рядок прив’язати порівняння бінінгу до його опівночі:
Використовуйте DATEADD(DAY, DATEDIFF(DAY, 0, aa.[date]), 0)
замість того, '2000'
де воно з’являється вище. Ваш запит буде абсолютно нечитабельним, але він спрацює.
Альтернативою може стати CONVERT(DATETIME, CONVERT(DATE, aa.[date]))
заміна.
† 2 32 ≈ 4.29E + 9, тож якщо ви DATEPART
є SECOND
, ви отримуєте 4,3 мільярда секунд з обох боків або "якір ± 136 років". Аналогічно, 2 32 мілісекунди - ≈ 49,7 дня.
‡ Якщо ваші дані насправді охоплюють століття чи тисячоліття і досі точні до другої чи мілісекунди… вітання! Що б ви не робили, продовжуйте робити це.
ROUND((DATEPART(MINUTE, DT.[Date]) / 5),0,1) * 5
так, що коли я дивлюся на дані, він співвідноситься з найближчим часовим інтервалом