Sql server MS SQL 2014-日期范围内重复发生的事件计数

Sql server MS SQL 2014-日期范围内重复发生的事件计数,sql-server,sql-server-2014,Sql Server,Sql Server 2014,我有一个表,跟踪为特定设备ID创建的事件ID的日期时间,我正试图找到一种方法来跟踪一系列日期内的慢性问题。慢性问题的定义是在过去5天内创建了3个或更多事件ID的任何设备ID。我需要能够搜索一系列不同的日期,主要是每月 给定表格: IF OBJECT_ID('tempdb.dbo.#temp') IS NOT NULL DROP TABLE #temp CREATE TABLE #temp (Device_ID INT, Incident_ID INT, Incident

我有一个表,跟踪为特定设备ID创建的事件ID的日期时间,我正试图找到一种方法来跟踪一系列日期内的慢性问题。慢性问题的定义是在过去5天内创建了3个或更多事件ID的任何设备ID。我需要能够搜索一系列不同的日期,主要是每月

给定表格:

IF OBJECT_ID('tempdb.dbo.#temp') IS NOT NULL
DROP TABLE #temp

CREATE TABLE #temp
    (Device_ID INT,
    Incident_ID INT,
    Incident_Datetime DATETIME)

INSERT INTO #temp
VALUES
    (2,1001,'2016-02-01'),
    (3,1002,'2016-02-02'),
    (2,1003,'2016-02-09'),
    (2,1004,'2016-02-10'),
    (5,1005,'2016-02-12'),
    (2,1006,'2016-02-13'),
    (5,1007,'2016-02-14'),
    (5,1008,'2016-02-15'),
    (3,1009,'2016-02-18'),
    (3,1010,'2016-02-19'),
    (3,1011,'2016-02-20'),
    (5,1012,'2016-02-21'),
    (3,1013,'2016-03-18'),
    (3,1014,'2016-03-19'),
    (3,1015,'2016-03-20');
2016年2月长期问题的预期结果为:

Device_ID   Incident_ID Incident_Datetime
2           1003            2/9/16 0:00
2           1004            2/10/16 0:00
2           1006            2/13/16 0:00
3           1009            2/18/16 0:00
3           1010            2/19/16 0:00
3           1011            2/20/16 0:00
5           1005            2/12/16 0:00
5           1007            2/14/16 0:00
5           1008            2/15/16 0:00
我尝试了以下查询,该查询显示了事件的递增计数,并允许我查找那些有慢性问题的设备ID,但我很难隔离构成慢性问题的所有事件,同时排除3天范围之外发生的异常值

SELECT c.Device_ID, c.Incident_ID, c.Incident_Datetime,
    (SELECT COUNT(*)
    FROM #temp AS t
    WHERE
        c.Device_ID = t.Device_ID
        AND
        t.Incident_Datetime BETWEEN DATEADD(DAY,-5,c.Incident_Datetime) AND c.Incident_Datetime) AS Incident_Count
FROM #temp AS c
WHERE
    c.Incident_Datetime >= '2016-02-01'
    AND
    c.Incident_Datetime < '2016-03-01'
ORDER BY 
    Device_ID, Incident_Datetime
这个怎么样

DECLARE @StartDate datetime, @EndDate datetime
SET @StartDate='2016-02-01'
SET @EndDate='2016-03-01'

SELECT c.Device_ID, c.Incident_ID, c.Incident_DateTime FROM #temp c
INNER JOIN (SELECT t.Device_ID, Count(*) FROM #temp
    WHERE t.Incident_DateTime BETWEEN DATEADD(dd, -3, c.Incident_DateTime) AND DATEADD(dd, +3, c.Incident_DateTime)
    GROUP BY t.Device_ID
    HAVING Count(*) > 2)) t ON c.Device_ID = t.Device_ID
AND c.Incident_DateTime BETWEEN @StartDate AND @EndDate
ORDER BY 
c.Device_ID, c.Incident_Datetime

以下是一种在n天内得出运行事件总数的方法:

with
incidents as (
    select * from #temp cross apply (
    select incident_datetime, 1 union all
    select incident_datetime + 5, -1) x(dt, delta)),
rolling as (
    select *, incidents_in_range = sum(delta)
        over (partition by device_id order by dt)
    from incidents)

select t.* from #temp t join rolling r
    on r.device_id=t.device_id
    and t.incident_datetime between r.incident_datetime - 5 and r.incident_datetime
where r.incidents_in_range >= 3

…基本上,找出5天内发生3起事件的时间点,然后在5天内加入事件。

这可能没有Jake的答案那么好,但这里有一个可行的替代解决方案:

        WITH cte AS 
        (
          SELECT tmp.Device_ID, tmp.Incident_Datetime FROM #temp AS tmp
          CROSS APPLY
          ( 
            SELECT Device_ID 
            FROM #temp AS t 
            WHERE tmp.Device_ID = t.Device_ID AND t.Incident_Datetime BETWEEN DATEADD(d,-5,tmp.Incident_Datetime) AND tmp.Incident_Datetime
            GROUP BY Device_ID HAVING COUNT(Incident_ID) >= 3 
          ) p
          WHERE tmp.Incident_Datetime BETWEEN '02-01-2016' AND '03-01-2016'
        )        

        SELECT f.*
        FROM #temp f
        INNER JOIN cte
        ON f.Device_ID = cte.Device_ID
        WHERE f.Incident_Datetime BETWEEN DATEADD(d,-5,cte.Incident_Datetime) AND cte.Incident_Datetime 
        GROUP BY f.Device_ID, f.Incident_ID, f.Incident_Datetime
        ORDER BY f.Device_ID, f.Incident_Datetime

谢谢你指出设备id的问题,我在约会的时候没有注意到。我已编辑答案以删除它们。当我运行您的查询时,我得到了一些奇怪的结果-device_id 2,incident_id 1004显示这是唯一的device_id 2条目,incident_datetime不正确。示例:对于设备识别号5,事件识别号1005,它显示为2016-02-15,当它应该是2016-02-12时,看起来像是从它使用的是来自联盟的日期时间statement@Jericho添加了一个来自联盟另一端的修复事件\u datetime。我无法使此事件正常工作。看起来在have COUNT*后面有一个额外的括号,但是它不能绑定t。和c。内部连接查询的标识符有些问题,这很有效,正是我克服这个问题给我带来的心理障碍所需要的替代方法。我将需要磨练交叉应用程序,因为它们不是我经常使用的东西,但它确实起到了作用!这是我第一次亲自使用它。它给了我很多关于未来如何使用它的想法。所以我很欣赏这种脑力锻炼