【发布时间】:2021-12-07 02:30:48
【问题描述】:
我的表结构如下:
Id, Message
1, John Doe
2, Jane Smith
3, Error
4, Jane Smith
有没有办法获取错误记录和周边记录?即查找所有错误及其前后的记录。
【问题讨论】:
-
首先你定义前后。没有保证顺序可以挑选出之前和之后的内容。
标签: sql sql-server tsql
我的表结构如下:
Id, Message
1, John Doe
2, Jane Smith
3, Error
4, Jane Smith
有没有办法获取错误记录和周边记录?即查找所有错误及其前后的记录。
【问题讨论】:
标签: sql sql-server tsql
;WITH numberedlogtable AS
(
SELECT Id,Message,
ROW_NUMBER() OVER (ORDER BY ID) AS RN
FROM logtable
)
SELECT Id,Message
FROM numberedlogtable
WHERE RN IN (SELECT RN+i
FROM numberedlogtable
CROSS JOIN (SELECT -1 AS i UNION ALL SELECT 0 UNION ALL SELECT 1) n
WHERE Message='Error')
【讨论】:
ROW_NUMBER() 来获得没有间隙的保证序列。该查询被放入一个公用表表达式中并使用了两次。一次找到有错误的行号。然后将其交叉连接到小表上,因此对于找到的每个行号,我们得到 3 个行号(上一个、目标和下一个)。一旦确定了感兴趣的行号,就会将其插入原始查询以检索相应的记录。
WITH err AS
(
SELECT TOP 1 *
FROM log
WHERE message = 'Error'
ORDER BY
id
),
p AS
(
SELECT TOP 1 l.*
FROM log
WHERE id <
(
SELECT id
FROM err
)
ORDER BY
id DESC
)
SELECT TOP 3 *
FROM log
WHERE id >
(
SELECT id
FROM p
)
ORDER BY
id
【讨论】:
调整这个例程来挑选你的目标。
DECLARE @TargetId int
SET @TargetId = 3
select *
from LogTable
where Id in (-- "before"
select max(Id)
from LogTable
where Id < @TargetId
-- target
union all select @TargetId
-- "after"
union all select min(Id)
from LogTable
where Id > @TargetId)
【讨论】:
select id,messag from
(Select (Row_Number() over (order by ID)) as RNO, * from #Temp) as A,
(select SubRNO-1 as A,
SubRNO as B,
SubRNO+1 as C
from (Select (Row_Number() over (order by ID)) as SubRNO, * from #Temp) as C
where messag = 'Error') as B
where A.RNO = B.A or A.RNO = B.B or A.RNO = B.C
【讨论】:
;WITH Logs AS
(
SELECT ROW_NUMBER() OVER (ORDER BY id), id, message as rownum FROM LogTable lt
)
SELECT curr.id, prev.id, next.id
FROM Logs curr
LEFT OUTER JOIN Logs prev ON curr.rownum+1=prev.rownum
RIGHT OUTER JOIN Logs next ON curr.rownum-1=next.rownum
WHERE curr.message = 'Error'
【讨论】:
select id, message from tbl where id in (
select id from tbl where message = "error"
union
select id-1 from tbl where message = "error"
union
select id+1 from tbl where message = "error"
)
【讨论】:
id 不连续怎么办?
2、3、4——例如它们! :)
NULLS:它只会返回比预期更少的记录。
使用 UNION 进行简单的高性能查询(我发现上面选择的答案 WITH 查询非常慢)
当您知道给定记录的 ID 或特定标识符,并且想要选择固定数量的记录 BEFORE 和 之后 该记录。需要一个数字字段作为 ID,或者可以按升序/降序排序的日期。
示例:您要选择记录特定错误前后的 10 条记录,您知道错误 ID,可以按日期或 ID 排序。
以下查询获取(包括)上面的 1 个结果、标识的记录本身以及下面的 1 个记录。在 UNION 之后,结果再次按降序排序。
SELECT q.*
FROM(
SELECT TOP 2
id, content
FROM
the_table
WHERE
id >= [ID]
ORDER BY id ASC
UNION
SELECT TOP 1
id, content
FROM
the_table
WHERE
id < [ID]
ORDER BY id DESC
) q
ORDER BY q.id DESC
【讨论】: