我可以改进这个查询吗?

Raf*_*off 0 performance t-sql sql-server-2008-r2 query-performance

SELECT * 
FROM   SameLogTable
WHERE  ID_Table IN (SELECT ID_Table-1
                    FROM   SameLogTable
                    WHERE  <SameCondition>) OR
       ID_Table IN (SELECT ID_Table
                    FROM   SameLogTable
                    WHERE  <SameCondition>) OR
       ID_Table IN (SELECT ID_Table+1
                    FROM   SameLogTable
                    WHERE  <SameCondition>)
Run Code Online (Sandbox Code Playgroud)

此查询在日志记录表上运行,我想选择特定事件,以及这些事件之前和之后的事件。这个解决方案感觉丑陋且效率低下,为此编写更好的方法是什么?

示例:如果我对 LogTable 的 ID 为 4 和 23 的行感兴趣,我想得到以下结果:

ID    Column1    Column2    ...
3     ...        ...
4     ...        ...
5     ...        ...
22    ...        ...
23    ...        ...
24    ...        ...
Run Code Online (Sandbox Code Playgroud)

这些都是来自同一 LogTable 的所有行,除了我使用 WHERE 指定第 4 行和第 23 行,并且我希望 Select 自动返回第 3,5 行(第 4 行)和第 22、24 行(第 23 行)。


总结结果:

MyQuery:     16s
UNION ALL:    4s
Join:        ~0s
Run Code Online (Sandbox Code Playgroud)

感谢您的回复!

ype*_*eᵀᴹ 7

假设它ID是表的主键(或具有唯一约束),您可以使用此变体:

SELECT t.* 
FROM   SameLogTable AS t
  JOIN ( SELECT id
         FROM   SameLogTable 
         WHERE  <SameCondition>
       ) AS c
       ON t.id = c.id -1
       OR t.id = c.id
       OR t.id = c.id +1 ;
Run Code Online (Sandbox Code Playgroud)

注意:如果id有差距,这很有可能,上面的方法不会按预期工作,您的原始查询也不会。ROW_NUMBER()可以帮助您:

; WITH cte AS
( SELECT t.*,
         rn = ROW_NUMBER() OVER (ORDER BY t.id)
  FROM   SameLogTable AS t
) 
SELECT t.*
FROM   cte AS t
  JOIN ( SELECT rn
         FROM   cte 
         WHERE  <SameCondition>
       ) AS c
       ON t.rn = c.rn - 1
       OR t.rn = c.rn
       OR t.rn = c.rn + 1 ;
Run Code Online (Sandbox Code Playgroud)