检索特定记录上方和下方的记录

时间:2012-09-21 18:01:38

标签: sql-server sql-server-2008

我经常验证SQLServer中的日志,我的查询通常看起来像这样(其中Type = 0表示错误):

SELECT * 
FROM Logs 
WHERE Type = 0 
ORDER BY Timestamp

但是大多数时候,我不仅对错误本身感兴趣,而且对错误发生之前发生的事情感兴趣。

使用SQLServer,是否有可能在查询的WHERE子句的每一行上查询上面/下面(相对于主键)的n行?

实施例。根据我的查询,我只能获得第125和第10行。 130.我想[123,124,125]和[128,129,130​​]。

PrimaryKey  Timestamp             Type  Description
123         2012-09-17 03:41:46.240 1   Working.
124         2012-09-17 03:42:46.240 1   Database backup.
125         2012-09-17 03:43:46.240 0   Access violation.
126         2012-09-17 03:44:46.240 1   Working.
127         2012-09-17 03:45:46.240 1   Working.
128         2012-09-17 03:46:46.240 1   Working.
129         2012-09-17 03:47:46.240 1   Backup.
130         2012-09-17 03:48:46.240 0   Corrupted.
131         2012-09-17 03:49:46.240 1   Working.

谢谢。

1 个答案:

答案 0 :(得分:2)

我会这样做:

SELECT 
    L2.* 
FROM 
    Logs L1
    JOIN Logs L2
    ON 
        L1.PrimaryKey = L2.PrimaryKey OR 
        L1.PrimaryKey = L2.PrimaryKey - 1 OR
        L1.PrimaryKey = L2.PrimaryKey + 1
WHERE
    L1.Type = 0

结果如下:

PrimaryKey  TS                      Type        Description
----------- ----------------------- ----------- -----------------
124         2012-09-17 03:42:46.240 1           Database backup.
125         2012-09-17 03:43:46.240 0           Access violation.
126         2012-09-17 03:44:46.240 1           Working.
129         2012-09-17 03:47:46.240 1           Backup.
130         2012-09-17 03:48:46.240 0           Corrupted.
131         2012-09-17 03:49:46.240 1           Working.

您可以使用关系运算符修改连接条件,以检索匹配行上方和下方的n行。

如果不保证PrimaryKey列是顺序的,那么假设记录始终按Timestamp顺序按ASC排序,以下查询将获取前后记录到选定的记录:

WITH LogsTable (PrimaryKey, TS, Type, Description, Rank) AS
(
    SELECT 
        PrimaryKey, 
        TS, 
        Type, 
        Description, 
        ROW_NUMBER() OVER (ORDER BY TS ASC) as 'Rank' 
    FROM 
        Logs
)
SELECT 
    L2.* 
FROM 
    LogsTable L1
    JOIN LogsTable L2
    ON 
        L1.Rank = L2.Rank OR 
        L1.Rank = L2.Rank - 1 OR
        L1.Rank = L2.Rank + 1
WHERE
    L1.Type = 0