2017-12-18 293 views
0

我在SQL Server 2016中有一个表,其中有数百万条日志,我们需要在存储过程中对其进行筛选。每个日志都有一个LogTime字段,我将使用这个过滤。我只想返回间隔超过15分钟的日志,跳过那些在LogTime方面彼此太接近的日志。按日期时间间隔筛选SQL行

日志一般在彼此的秒钟之内,所以此时间间隔将适当地限制日志。我也不在乎跳过大部分日志项目。如果下一个日志距离数小时,只要间隔至少为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知识并没有延伸到很远,我一直无法创建一个在任何体面时间内运行的解决方案。

+0

我们无法找到一个令人满意的SQL解决方案,以我们的问题,所以我们采用分块请求到数据库,然后请求下一块之前筛选的服务器上的组合策略。 – Iyashu5040

回答

0

试试这个。

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个不同的时间槽或时间戳当前时间,这是有史以来第一个

0

这是太长的评论。

正如你所描述的那样,这将会是相当昂贵的计算。你可以使用递归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; 
0

一个简单的方法来做到这一点是使用一个查询,看起来像这样它得到以前的时间为每个记录并计算它们之间的分钟数。

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