2017-08-04 61 views
0

我需要找到每个用户在'失败'时具有特定状态的最新3条记录。起初看起来很简单,但我似乎无法做到。找到相同状态的最新3条记录

所以在一个表:

ID   Date   Status 
1   2017-01-01  Fail 
1   2017-01-02  Fail 
1   2017-02-04  Fail 
1   2015-03-21  Pass 
1   2014-02-19  Fail 
1   2016-10-23  Pass 
2   2017-01-01  Fail 
2   2017-01-02  Pass 
2   2017-02-04  Fail 
2   2016-10-23  Fail 

我希望ID 1返回为最近3个记录是失败的,但不是ID 2,因为他们有内他们的三个失败的通行证。每个用户可能有任何数量的通过和失败记录。有成千上万个不同的ID

到目前为止,我已经尝试了使用ROW_NUMBER()命令进行尝试的CTE,但无法想出一种方法来确保最新的三个结果都具有相同的Fail状态。

预期结果

ID Latest Fail Date Count 
1 2017-02-04   3 
+0

向我们展示您的查询的尝试! – jarlh

+1

你可以添加预期的结果fot它 –

+0

@jarlh查询尝试不起作用,所以没有多少点显示它 - 我做了几次尝试,所以我不只是寻找一个简单的答案放心。 – bhs

回答

2

也许尝试这样的事:

WITH cte 
AS 
(

SELECT id, 
     date, 
     status, 
     ROW_NUMBER() OVER (PARTITION BY id ORDER BY date DESC) row 
FROM #table 


),cte2 
AS 
(

SELECT id, max(date) as date, count(*) AS count 
FROM cte 
WHERE status = 'fail' 
AND row <= 3 
GROUP BY id 
) 

SELECT id, 
     date AS latest_fail, 
     count 
FROM cte2 
WHERE count = 3 
+0

只是测试这个,我敢肯定它工作正常 - 谢谢:-) – bhs

+0

不用担心队友:) – VDK

0

检查。

演示:Here

with CTE as 
(
select *,ROW_NUMBER() over(partition by id order by date desc) rnk 
from temp 
where Status ='Fail' 
) 
select top 1 ID,max(DATE) as Latest_Fail_Date ,COUNT(rnk) as count 
from CTE where rnk <=3 
group by ID 

Ouptut:

enter image description here

+0

这很好,但有成千上万的ID,每一个都有他们的Pass.Fails的历史等我需要一个查询给我一个所有ID匹配的列表匹配该模式。我编辑了这个问题,因为之前并不清楚。 – bhs

+0

@bhs我不能得到你想要的。?哪个pattenr?ID是用户ID? –

+0

一个匹配三个最新失败记录模式的所有ID的列表 – bhs

0

我想你可以使用cross apply做到这一点:

select i.id 
from (select distinct id from t) i cross apply 
    (select sum(case when t.status = 'Fail' then 1 else 0 end) as numFails 
     from (select top 3 t.* 
      from t 
      where t.id = i.id 
      order by date desc 
      ) ti 
    ) ti 
where numFails = 3; 

注意:你可能有一个表的所有ID。如果是这样,你使用它而不是select distinct子查询。

,或类似:

select i.id 
from (select distinct id from t) i cross apply 
    (select top 3 t.* 
     from t 
     where t.id = i.id 
     order by date desc 
    ) ti 
group by i.id 
having min(ti.status) = 'Fail' and max(ti.status) = 'Fail' and 
     count(*) = 3; 
0

在这里你去:

declare @numOfTries int = 3; 

with fails_nums as 
(
     select *, row_number() over (partition by ID order by [Date] desc) as rn 
     from #fails 
) 
select ID, max([Date]) [Date], count(*) as [count] 
from fails_nums fn1 
where fn1.rn <= @numOftries 
group by ID 
having count(case when [Status]='Fail' then [Status] end) = @numOfTries 

Example here

+0

我喜欢这样,因为它很优雅,很容易阅读(我以前没有用过),但它不起作用。如果有一个失败的单行也会被返回。 – bhs

+0

我的坏=(更正了查询 –