Если ваш общий набор данных не очень велик, вы можете go с помощью простого коррелированного подзапроса.
SELECT d.ModuleID, d.OperationID, d.datm
, (
SELECT count(*)
FROM d d2
WHERE d.ModuleID = d2.ModuleID
AND d2.datm >= d.datm
AND d2.datm <= DATEADD(minute, 15, d.datm)
) AS SatisfyingEntries
, ( SELECT count(*) FROM d d3 ) AS TotalRecords
FROM d
ORDER BY d.ModuleID, d.datm
Но если этот набор данных больше, чем несколько тысяч строк, вы можете посмотреть в Причудливом обновлении, которое я предложил выше. Хотя делают немного разные вещи.
Обратите внимание, что этот запрос вычисляет для 15 минут ПОСЛЕ события, поэтому это не настоящее скользящее 15-минутное окно. Это совершенно другая проблема, с которой должно работать Quirky Update.
Также обратите внимание, что этот запрос показывает необходимость в хороших индексах для этой таблицы.
И последнее примечание: если TotalRecords всегда будет подсчетом всех записей, вам может быть лучше получить это в другом запросе, в зависимости от того, как вы планируете использовать эти данные.