我有一张发生过失败事件的表。我需要找出例如两分钟内是否记录了五次失败。
Id Created EventType Description
1 2015-11-16 15:10:16 1 test
2 2015-11-16 15:12:17 1 test
3 2015-11-16 15:12:18 1 test
4 2015-11-16 15:12:19 1 test
5 2015-11-16 15:12:20 1 test
6 2015-11-16 15:13:16 1 test
7 2015-11-16 16:15:43 1 test
所以在这个例子中,将选择事件2-6。然后我需要选择期间的开始和结束时间。
甚至不知道从哪里开始,显然它是在比较两行。我想过使用光标但不确定是否有任何我可以使用的聪明分组。
答案 0 :(得分:1)
不是全部,但应该让你开始
UsedRange.Value
如果您知道ID将按顺序使用,可以在t2.ID>上使用t1.ID
这可能不是我从内存中做到的确切的DateDiff语法
假设你在一个范围内有7个。这将报告任何(多个)5组。您需要对您想要的内容非常具体。
答案 1 :(得分:1)
您可以使用CROSS APPLY
初步选择事件2-6:
SELECT t1.Id, t1.EventType, t1.Created AS StartTime, t3.EndTime
FROM mytable AS t1
CROSS APPLY (
SELECT TOP 1 t2.Id, t2.Created
FROM mytable AS t2
WHERE t1.EventType = t2.EventType AND
t2.Id <> t1.Id AND
ABS(DATEDIFF(ss, t1.Created, t2.Created)) <= 60
ORDER BY DATEDIFF(ss, t1.Created, t2.Created) DESC) AS t3(Id, EndTime)
<强>输出:强>
Id EventType StartTime EndTime
2 1 2015-11-16 15:12:17.000 2015-11-16 15:13:16.000
3 1 2015-11-16 15:12:18.000 2015-11-16 15:13:16.000
4 1 2015-11-16 15:12:19.000 2015-11-16 15:13:16.000
5 1 2015-11-16 15:12:20.000 2015-11-16 15:13:16.000
6 1 2015-11-16 15:13:16.000 2015-11-16 15:12:20.000
您现在可以检查记录存储桶是否包含5行或更多行,并使用GROUP BY
获取第一个/最后一个记录:
SELECT MIN(t1.Id) AS StartID,
MAX(t3.Id) AS EndID,
t1.EventType,
MIN(t1.Created) AS StartTime, MAX(t3.EndTime) AS EndTime
FROM mytable AS t1
CROSS APPLY (
SELECT TOP 1 t2.Id, t2.Created
FROM mytable AS t2
WHERE t1.EventType = t2.EventType AND
t2.Id <> t1.Id AND
ABS(DATEDIFF(ss, t1.Created, t2.Created)) <= 120
ORDER BY DATEDIFF(ss, t1.Created, t2.Created) DESC) AS t3(Id, EndTime)
GROUP BY t1.EventType
HAVING COUNT(*) >= 5
<强>输出:强>
StartID EndID EventType StartTime EndTime
2 6 1 2015-11-16 15:12:17.000 2015-11-16 15:13:16.000
修改强>
另一种方法是使用Recursive CTE
:
;WITH CTE_RN AS (
SELECT Id, EventType, Created,
ROW_NUMBER() OVER (ORDER BY Created) AS rn
FROM mytable
), CTE_Buckets AS (
-- Anchor member: Get first row from table
SELECT Id, EventType, Created, CAST(1 AS BIGINT) AS row_num,
1 AS bucket_num, 0 AS time_diff
FROM CTE_RN
WHERE rn = 1
UNION ALL
-- Recursive member: Get next row. Reset time diff cumulative counter
-- if time difference exceeds two minutes
SELECT c1.Id, c1.EventType, c1.Created, c1.rn AS row_num,
-- All consecutive rows within the 2 minute time range fall within the same bucket
bucket_num = CASE
WHEN x.diff + time_diff > 120 THEN c2.bucket_num + 1
ELSE c2.bucket_num
END,
-- Calculate cummulative time diff.
time_diff = CASE
WHEN x.diff + time_diff > 120 THEN 0
ELSE x.diff + time_diff
END
FROM CTE_RN AS c1
INNER JOIN CTE_Buckets AS c2 ON c1.rn = c2.row_num + 1
CROSS APPLY (SELECT DATEDIFF(ss, c2.Created, c1.Created)) AS x(diff)
)
SELECT MIN(Id) AS StartID, MAX(Id) AS EndID,
MIN(Created) AS StartTime, MAX(Created) AS EndTime
FROM CTE_Buckets
GROUP BY bucket_num
HAVING COUNT(*) >= 5
此查询处理多个间隔组。