我在SQL Server 2016中有一个表,其中包含数百万个日志,我们需要在存储过程中对其进行过滤。每个日志都有一个LogTime
字段,我将用于此过滤。我想只返回相隔超过15分钟的日志,跳过那些在LogTime
方面彼此太接近的日志。
日志通常在几秒钟之内,因此该时间间隔将适当地限制日志。我也不关心跳过大多数日志项。如果下一个日志距离小时数,则日志之间的间隔大于15分钟也无关紧要,只要间隔时间至少为15分钟。
因此,例如,第一个日志是在15:30,跳过所有日志,直到15:45。在15:46找到下一个日志并继续这样做。
我需要的输出示例:
15:30 - Log Content
15:46 - Log Content
16:12 - Log Content
18:00 - Log Content
我一直在通过反复试验来搜索各种各样的东西。不幸的是,我的SQL知识并没有延伸到很长时间,而且我无法创建一个在任何体面的时间范围内运行的解决方案。
试试这个。
WITH CTE
AS
(
SELECT
SeqNo = 1,
LogTime = MIN(LogTime)
FROM LogTable
UNION ALL
SELECT
SeqNo = SeqNo+1,
LogTime = DATEADD(MINUTE,15,LogTime)
FROM CTE
WHERE LogTime < GETDATE()
OR SeqNo < 100
)
SELECT
*
FROM LogTable LT
WHERE EXISTS
(
SELECT 1 FROM CTE WHERE LogTime = LT.LogTime
)
这将显示日志表开头的所有记录,间隔为15分钟。直到100个不同的时间段或时间表当前时间,这是第一次
这个评论太长了。
正如您所描述的那样,它的计算成本非常高。您可以使用递归CTE或游标来解决它。这两种方法都需要很长时间。
有两种选择。第一种是将每个日期/时间截断为15分钟,然后拉出第一个。你可以这样做:
select t.*
from (select t.*,
row_number() over (partition by cast(logtime as date), datepart(hour, logtime), datepart(minute, logtime) / 4
order by logtime) as seqnum
from t
) t
where seqnum = 1;
另一种方法是在存在15分钟或更长的间隙时按顺序取第一个。为此,请使用lag()
:
select t.*
from (select t.*, lag(logtime) over (order by logtime) as prev_logtime
from t
) t
where logtime > dateadd(minute, 15, prev_logtime) or prev_logtime is null;
一种简单的方法是使用类似于此的查询,该查询获取每个记录的上一次时间并计算它们之间的分钟数。
SELECT * FROM YourTable
WHERE DateDiff(mi, (SELECT TOP 1 LogTime FROM YourTable as sub
WHERE YourTable.LogTime > sub.LogTime ORDER BY LogTime DESC), LogTime) > 15