如何在给出之前获得N条记录?
我有以下表结构:
Id, Message
1, John Doe
2, Jane Smith
3, Error
4, Jane Smith
5, Michael Pirs
7, Gabriel Angelos
8, Error
有没有办法在每个错误之前获取N条记录并加入所有这些记录? 因此,N = 2的预期结果将是
1, John Doe
2, Jane Smith
5, Michael Pirs
7, Gabriel Angelos
答案 0 :(得分:3)
如果您的ID没有间隙增加,则需要创建一个行号列。然后你可以使用一个简单的连接来找到前面的N.你之前的N可能会重叠...所以如果你不想要重复,你必须添加distinct
。
declare @N as integer
set @N=2
;with cte_tbl (Id, Message, rownum) AS
(
select *, ROW_NUMBER() over (order by id) as rownum from test
)
select distinct Prev.Id, Prev.Message
from cte_tbl
join cte_tbl Prev
on Prev.rownum between cte_tbl.rownum-@N and cte_tbl.rownum-1
where cte_tbl.Message = 'Error'
and Prev.Message <> 'Error'
order by Prev.Id
如果之前的@N
条记录之一是错误,则“错误”记录将不会显示。如果您希望包含这些内容,则必须进行修改。只需删除行and Prev.Message <> 'Error'
。
答案 1 :(得分:0)
您可以使用cross apply
执行此操作。逻辑与典型应用程序略有不同,因为您只需要来自cross apply
子查询的记录:
select t2.*
from table t cross apply
(select top 2 t.*
from table t2
where t2.id < t.id
order by t2.id desc
) t2
where t2.message = 'Error';
对于那些倾向的人,还有一种使用窗口函数的方法,但它有点麻烦。执行Error
记录的反向累积和以识别给定错误之前的值。然后枚举这些并选择你想要的那些:
select t.id, t.message
from (select t.*, row_number() over (partition by grp order by id desc) as seqnum
from (select t.*,
sum(case when message = 'Error' then 1 else 0 end) over
(order by id desc)) as grp
from table t
) t
where seqnum between 2 and 3;
请注意,过滤器介于2和3之间,因为'Error'
的值为1。
答案 2 :(得分:0)
获取所有'错误'的行并加入前面的id。假设您的ID是连续的。如果他们没有获得帮助或ROW_NUMBER()的连续ID。
你可以试试这个:
select
T.*
from (
select
id iderror
from myTable
where
Message = 'Error'
) errorRows
inner join myTable T on
T.id between errorRows.iderror -2 and errorRows.iderror -1 and
T.Message <> 'Error'
答案 3 :(得分:0)
如果您使用ID的标识字段,这会更容易一些,那么您将拥有连续的数字,但您可以使用此方法。我正在对行进行排名,然后在错误之前返回那些行。
select t1.Rank_ID, t1.id, t1.message, te.id
from (select rank() over(order by id) as Rank_ID, id, message from tbl_test) t1
inner join (select rank() over(order by id)as Rank_ID, id, message from tbl_test) te
on t1.Rank_ID between te.Rank_ID-2 and te.Rank_ID-1
where te.message='Error'