SQL-запрос для агрегирования DateDiff, превышающего заданное значение
Вопрос
У меня есть таблица журналов, используемая для «пульсов» устройства.У меня есть сетевые устройства, которые проверяют соединение с сервером каждые 10 минут.Нам нужна статистика о том, когда они пропускают запланированное время регистрации.У меня есть запрос, который может делать это для каждого устройства, но мне нужно изменить его для обработки на всех устройствах.
Таблица пульса выглядит так:
CREATE TABLE [dbo].[DeviceHeartbeat](
[Id] [int] IDENTITY(1,1) NOT NULL,
[DeviceId] [int] NULL,
[CheckinTime] [datetime] NULL,
[Runtime] [int] NULL,
PRIMARY KEY CLUSTERED
([Id] ASC)) ON [PRIMARY]
Устройство проверяет сервер, сервер добавляет в эту таблицу строку со своим идентификатором, временем проверки и временем выполнения устройства (аппаратное значение, отправленное устройством).Запрос, который у меня есть на данный момент, выглядит так:
WITH t AS
(
SELECT Checkintime, rn = ROW_NUMBER() OVER (ORDER BY Checkintime)
FROM DeviceHeartbeat
WHERE DeviceId = 1112
),
x AS
(
SELECT d = DATEDIFF(MINUTE, t1.Checkintime, t2.Checkintime)
FROM t AS t1
INNER JOIN t AS t2
ON t1.rn = t2.rn - 1
),
y AS
(
SELECT stats = CASE WHEN d < 10 THEN ' < 10 '
WHEN d BETWEEN 10 AND 11 THEN '10 - 11 '
WHEN d BETWEEN 11 AND 12 THEN '11 - 12 '
ELSE '+12 ' END + ' minutes:'
FROM x
)
SELECT stats, COUNT(*) FROM y GROUP BY stats;
Этот запрос ограничен одним указанным устройством.Пример результатов выглядит следующим образом:
stats
----------------- ----
< 10 minutes: 1536
10 - 11 minutes: 425
11 - 12 minutes: 952
+12 minutes: 160
В идеале меня интересуют только проверки длительностью более 12 минут.Итак, мне нужен был список устройств, у которых время регистрации превышает 12 минут, упорядоченный по их количеству.Это позволит мне увидеть 10 или 20 устройств, время регистрации которых превышает 12 минут, и предупреждать меня о проблемных устройствах.Что-то вроде:
DeviceId CheckinsOver12Mins
---------- -------------------
1112 160
1108 152
15 114
106 86
Предложения?
Решение
Попробуй это:
WITH t AS
(
SELECT Checkintime, DeviceID, rn = ROW_NUMBER() OVER (ORDER BY DeviceID, Checkintime)
FROM DeviceHeartbeat
),
x AS
(
SELECT t1.deviceID, d = DATEDIFF(MINUTE, t1.Checkintime, t2.Checkintime)
FROM t AS t1
INNER JOIN t AS t2
ON t1.rn = t2.rn - 1 and t1.DeviceID = t2.DeviceID
),
y AS
(
SELECT deviceID
FROM x
WHERE d > 12
)
select deviceID, count(deviceID) as [Checkins over 12 mins] FROM y GROUP BY deviceID
Примечание:Нет тестовых данных — не проверял, могут быть опечатки.
Это должно быть y CTE, которое можно удалить и изменить, сделав его меньшим запросом:
select deviceID, count(deviceID) as [Checkins over 12 mins]
FROM x
GROUP BY deviceID
HAVING d > 12