【问题标题】:How do I get records before and after given one?如何在给定之前和之后获取记录?
【发布时间】:2021-12-07 02:30:48
【问题描述】:

我的表结构如下:

Id, Message
1, John Doe
2, Jane Smith
3, Error
4, Jane Smith

有没有办法获取错误记录和周边记录?即查找所有错误及其前后的记录。

【问题讨论】:

  • 首先你定义前后。没有保证顺序可以挑选出之前和之后的内容。

标签: sql sql-server tsql


【解决方案1】:
;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')

【讨论】:

  • 你能通俗点解释一下吗?如果没有,不用担心。还是谢谢。
  • 因为我们不知道您的 id 序列是否可以有间隙,所以我使用ROW_NUMBER() 来获得没有间隙的保证序列。该查询被放入一个公用表表达式中并使用了两次。一次找到有错误的行号。然后将其交叉连接到小表上,因此对于找到的每个行号,我们得到 3 个行号(上一个、目标和下一个)。一旦确定了感兴趣的行号,就会将其插入原始查询以检索相应的记录。
  • @MartinSmith,你能帮我解决这个问题吗:stackoverflow.com/questions/59299909/…
【解决方案2】:
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

【讨论】:

  • +1 - 很好地处理 ID 列中的空白,应该运行得很快。
【解决方案3】:

调整这个例程来挑选你的目标。

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)

【讨论】:

    【解决方案4】:
    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
    

    【讨论】:

      【解决方案5】:
      ;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'
      

      【讨论】:

        【解决方案6】:
        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 不连续怎么办?
        • 它不起作用;但在给出的示例中,它们是连续的。
        • @Nim:你也可以硬编码234——例如它们! :)
        • @Nim:从表中删除记录也很常见。
        • @JNK:它既不会失败也不会返回 NULLS:它只会返回比预期更少的记录。
        【解决方案7】:

        获取目标前后的固定行数

        使用 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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-21
          • 1970-01-01
          • 2010-12-04
          • 2011-04-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多