查找状态相同的最新3条记录

时间:2017-08-04 10:03:56

标签: sql sql-server-2012 common-table-expression

我需要为每个具有“失败”特定状态的用户找到最新的3条记录。起初看起来很容易,但我似乎无法做对。

所以在表格中:

 <tr>
  <td style="font-family: 'Josefin Sans', sans-serif;font-size: 100%;">
  Does our applying process live up to your expectations?  <br/>
    <input type="radio" class="myCheckbox2" id="0" name="XX" value="Strongly Agree" >Strongly Agree<br>
    <input type="radio" class="myCheckbox2" id="0" name="XX" value="Somewhat Agree" >Somewhat Agree <br>
    <input type="radio" class="myCheckbox1" id="0" name="XX" value="Neither Agree nor Disagree" >Neither Agree nor Disagree<br>
    <input type="radio" class="myCheckbox1" id="0" name="XX" value="Somewhat Disagree" >Somewhat Disagree<br>
    <input type="radio" class="myCheckbox1" id="0" name="XX" value="Strongly Disagree" >Strongly Disagree<br>
    <input type="radio" class="myCheckbox2" id="0" name="XX" value="Not Applicable" >Not Applicable <br>
  </td>
 </tr>

我希望返回ID 1,因为最近的3条记录失败,但不是ID 2,因为它们在三条记录中都有通过失败。每个用户可以有任意数量的通过和失败记录。有数千种不同的ID

到目前为止,我已经尝试过使用ROW_NUMBER()的CTE对这些尝试进行排序,但无法想出确保最新的三个结果都具有相同状态Fail的方法。

预期结果

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

4 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分: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;

答案 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