【问题标题】:Find the latest 3 records with the same status查找最新的 3 条状态相同的记录
【发布时间】:2017-08-04 10:03:55
【问题描述】:

我需要为每个具有特定“失败”状态的用户查找最新的 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() 对尝试进行排序,但想不出一种方法来确保最新的三个结果都具有相同的 Fail 状态。

预期结果

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

【问题讨论】:

  • 向我们展示您的查询尝试!
  • 你能添加预期的结果吗
  • @jarlh 查询尝试不起作用,所以显示它没有多大意义 - 我已经做了几次尝试,所以我不只是在寻找一个简单的答案。
  • @Mr.Bhosale 我已编辑问题以包含预期结果
  • @bhs 我在输入表中看不到日期“2017-02-24”?你能重新检查两个 i/o

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


【解决方案1】:

不妨试试这样的:

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

【讨论】:

  • 只是测试一下,我确定它工作正常 - 谢谢 :-)
  • 别担心,伙计:)
【解决方案2】:

检查一下。

演示: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

输出:

【讨论】:

  • 这很好,但是有数千个 ID,每个 ID 都有他们的 Pass.Fails 等历史记录。我需要一个查询来给我一个与模式匹配的所有 ID 的列表。我已经编辑了这个问题,因为这之前不清楚。
  • @bhs 我无法得到你想要的东西。?哪个 pattenr ?ID 是用户 ID ?
  • 与三个最新失败记录的模式匹配的所有 ID 的 .list
【解决方案3】:

我认为你可以使用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;

【讨论】:

    【解决方案4】:

    给你:

    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

    【讨论】:

    • 我喜欢这个,因为它非常优雅且易于阅读(而且我以前没有使用过 ALL),但它不起作用。如果有单行失败,也会返回。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    相关资源
    最近更新 更多