如何获取相邻记录?

时间:2011-05-31 23:19:21

标签: mysql sql database relational-database

不确定这在纯SQL中是否可行(或值得做),但无论如何我都会问。

假设我的数据库中有一堆编号的记录(为清晰起见,还有额外的空格):

2 3 4     10 11 12 13     55 56 57  91     106 107

现在给出一个诸如“11”之类的数字我怎样才能找回“10,11,12,13”?即所有相邻的记录没有间隙(所有数字必须彼此+/- 1)。

这可能吗?如果是这样,怎么样?

4 个答案:

答案 0 :(得分:3)

这应该可以解决问题。 @target_id是您的目标值(在给定示例中为11)。

  • 找到所需范围的下限 - 小于或等于目标的最大值value-1不存在。
  • 找到所需范围的上限 - 大于或等于value+1不存在的目标的最小值。
  • 返回行,使下限< = x< =上限

容易!

select *
from foo t
where t.id >= ( select max(id)
                from foo x
                where x.id <= @target_id
                  and not exists ( select *
                                   from foo x1
                                   where x1.id = x.id - 1
                                 )
              )
  and t.id <= ( select min(id)
                from foo y
                where y.id >= @target_id
                  and not exists ( select *
                                   from foo y1
                                   where y1.id = y.id + 1
                                 )
              )

索引您的ID /序列号列,我相信性能应该非常好。

答案 1 :(得分:1)

我什么都想不到。但如果读取速度很重要,您可以考虑添加一个代表“群集”的字段。 对于2,3和4,群集将为2.对于10,11,12和13,群集将为10,依此类推。

缺点是您必须在更新任何内容时更新群集。好的部分是算术可能非常容易。

答案 2 :(得分:1)

在不知道背景的情况下,我不能评论它是否值得(我假设没有证明不是这样),但任何事情都是可能的!我将首先使用一种方法的伪代码...

创建采用起始行ID的存储过程,其执行:

  • 创建一个ID的临时表
  • 将选择查询插入到与行ID匹配的主表中的临时表中
  • 虽然之前执行的插入数量为0:
        插入将临时表与主表连接的选择查询     其中ID的减法的绝对值等于
        到1,并且ID不在临时表中
  • 从临时表中选择结果,并加入ID上的主表。

    给出11的示例,第一个插入将插入#11,循环将开始,第二个插入将插入#10和#12,第三个插入将仅添加#13,第四个插入将插入0个记录,结束循环。然后你可以从ID的10,11,12,13的主表中选择。

    如果程序使用不存在的数字(如#14)运行,则循环将永远不会启动,并且您将得到一个空的结果集。

    你认为你能够完成这项任务还是应该写作?

  • 答案 3 :(得分:0)

    假设条目都是不同的,我们在支持窗口和CTE的DB中,

    WITH t1 AS
    ( SELECT id, id-row_number() OVER (ORDER BY id) AS discrepancy FROM t )
    SELECT id FROM t1 WHERE t1.discrepancy = 
      (SELECT discrepancy FROM t1 WHERE id=?);
    

    我认为这并不像尼古拉斯的代码那么快,但它可能值得一个实验(如果你的数据库完全能够提供这个查询)。