2016-09-13 42 views
1

我想选择与我的表中的id列表相匹配的所有行,其中包括之前的2行和之后的2行。按ID排序。为ID列表包含多个周围的行(按ID排序)

ID | Value 
---+---------- 
    1 | Value #1 
    2 | Value #2 
    3 | Value #3 
    4 | Value #4 
    5 | Value #5 
    6 | Value #6 
    7 | Value #7 
    8 | Value #8 
    9 | Value #9 
10 | Value #10 
11 | Value #11 
12 | Value #12 
13 | Value #13 
14 | Value #14 
17 | Value #17 
19 | Value #19 
20 | Value #20 
28 | Value #28 
29 | Value #29 
30 | Value #30 

现在我已经查询:

SELECT `ID`, `Value` FROM `table` WHERE `ID` in (5, 14) ORDER BY `ID`; 

如何延长它也返回编号3,4,6,7日和12,13,17,19?我不知道确切的ID。表格中可能存在空白。如果5不匹配,则不应退回3,4,6和7。

我已经阅读了有关“周围行”的所有其他问题。但他们都处理一个结果,应该包括周围的行。

+0

如果例如5个不在表格中,但是6和7是什么?你还想要退回吗? – Mureinik

+0

您可以为每行分配一个等级(有效消除间隙需求),然后连接两个等级内的行 - 螺母mureiniks问题有效;如果目标行丢失,您是否还想要返回相邻行 – Strawberry

+0

如果5不匹配,则不应返回3,4,6和7。 – SuperNova

回答

0

您可以使用下面的查询:

SELECT ID, Value 
FROM (
    SELECT ID, Value, 
      @rn1 := @rn1 + 1 AS rn 
    FROM mytable 
    CROSS JOIN (SELECT @rn1 := 0) AS v 
    ORDER BY ID) AS t1 
JOIN (
    SELECT rn 
    FROM (
     SELECT ID, Value, 
      @rn := @rn + 1 AS rn 
     FROM mytable 
     CROSS JOIN (SELECT @rn := 0) AS v 
     ORDER BY ID) AS t 
    WHERE t.ID IN (5, 14) 
) AS t2 ON t1.rn BETWEEN t2.rn - 2 AND t2.rn + 2 

上面的查询使用变量两次:第一次行号分配给每个记录,第二次以过滤周围的记录。

Demo here

+0

我认为sql服务器将使用此版本在内存中创建一个完整的表副本。我的表格最多可以有10.000.000行。我是我必须引入一个'索引'栏来避免这个副本。但是,删除一行时,速度很慢。 – SuperNova

+0

@SuperNova不幸的是,MySQL不支持窗口函数,所以没有简单的方法来实现这样的查询。您是否使用实际数据尝试了这个查询? –

+1

升级到MariaDB 10.2并使用其窗口功能。他们非常适合这样的查询。 –