创建一个获取行及其相邻行的查询

Create a query that fetches rows plus their adjacent rows

我在处理特定查询时遇到问题 - 分别首先创建查询。
这些列可以减少为 idsecondsstatus.

=============================
|  id  | seconds |  status  |
-----------------------------
|   0  |     0   |     0    |
|   1  |    12   |     1    |
|   2  |    25   |     0    |
|   3  |    37   |     1    |
|   4  |    42   |     0    |
=============================

我想要的是:所有带有 status = 1 的条目加上所有与这些条目相距不到 10 秒的条目。 基本上,我想获取所有可能的行对(或三元组等)以手动(稍后自动)检查它们是否需要配对(为此目的有一列 parent_id,但我们不需要它用于查询).我可以在代码中执行此操作(首先 select 所有 status=1,然后循环),但我想知道是否可以完全在数据库中执行此操作。

因此,我想要的输出如下:

=============================
|  id  | seconds |  status  |
-----------------------------
|   1  |    12   |     1    | <- status = 1
|   3  |    37   |     1    | <- status = 1
|   4  |    42   |     0    | <- only 5 seconds after status = 1
=============================

我目前最好的猜测是:

SELECT * FROM entries e0 
WHERE 
  e0.status = 1 OR 
  e0.status = 0 AND
  0 < (SELECT count(*) 
       FROM entries e1 
       WHERE e1.status = 1 AND abs(e1.seconds - e0.seconds) < 10)

但这会获取整个 table,我真的不知道为什么 - 这样做需要很长时间(列 seconds 上有一个索引,table 有 9000 个条目)。

有没有办法做到这一点(甚至可能有效)?

这是 union allexists 的一个选项:

select * from entries where status = 1
union all
select * from entries e where status = 0 and 
  exists (select 1
          from entries e2 
          where e2.status = 1 and
                abs(e.seconds - e2.seconds) < 10
          )

或者您可以使用 outer joindistinct 而不是 exists:

select distinct e.*
from entries e
  left join entries e2 on e2.status = 1 
where e.status = 1 or abs(e.seconds - e2.seconds) < 10

我更喜欢在单个查询中完成。但是,也有一些方法可以使用 exists 或子查询来实现。使用外部联接意味着您可以使用精心设计的 where 和 join 语句一次获取所有内容,根据您的性能情况添加 group by 或 distinct 将整理您的结果并使它们成为唯一的行。

关于在何处声明以确保满足您的意图,我的建议是使用括号来确定您的预期优先级。它将使您的代码更清楚您的意图。

WHERE Con​​dition1 = True OR Condition2 = True AND Condition3 = True

应该是

WHERE Con​​dition1 = True 或(Condition2 = True AND Condition3 = True)

奇怪的是,由于过去的经验,我不会认为它会以您提到的方式进行评估,但话又说回来,我总是使用括号来确定我的优先级,以便更清楚、更容易地制定更复杂的条件。

你得到整个的原因 table。是因为你table里面的数据。说真的,有时我们会去寻找答案并使它变得复杂,我更喜欢我的方式来解决你的查询,但给定你的结果集示例,我的查询和你的查询得到相同的结果!尝试将 10 秒更改为 1/2/3 等,看看您的查询效果如何。我的假设是在您的完整数据集中,您的任何状态为 0 的记录都在状态为 1 的记录的 10 秒内......我会回复,但这是我的第一个问题之一已回答

下面是一些基于您的数据集和查询的示例代码。

DECLARE @Entries AS TABLE (
    Id INT
    ,Seconds INT
    ,[Status] BIT
)

INSERT INTO @Entries (Id, Seconds, [Status])
VALUES (0,0,0 )
,(1,12,1 )
,(2,25,0 )
,(3,37,1 )
,(4,42,0 )

SELECT *
FROM
    @Entries e0
WHERE
    e0.Status = 1
    OR e0.Status = 0
    AND 0 < (SELECT count(*)
          FROM
             @Entries e1
          WHERE e1.Status = 1 AND ABS(e1.Seconds - e0.Seconds) < 10)

SELECT DISTINCT
    e0.*
FROM
    @Entries e0
    LEFT JOIN @Entries e1
    ON e1.[Status] = 1
    AND ABS(e1.seconds - e0.seconds) < 10
WHERE
    e0.[Status] = 1
    OR e1.id IS NOT NULL