MySQL查询-自定义排序结果的前后行

MySQL查询-自定义排序结果的前后行,sql,mysql,sql-order-by,Sql,Mysql,Sql Order By,我在StackOverflow中看到了其他类似的问题,但它们都基于自动递增ID,但我没有 我有一个类似这样的问题: SELECT field_a, field_b from table where field_m = '100' and field_n = '200' order by field_x 这就导致了这种情况 field_a field_b ------------------- john 12 mar

我在StackOverflow中看到了其他类似的问题,但它们都基于自动递增ID,但我没有

我有一个类似这样的问题:

  SELECT field_a, 
         field_b 
    from table
   where field_m = '100' 
     and field_n = '200'
order by field_x
这就导致了这种情况

field_a    field_b
-------------------
john       12     
marty      7     
peter      2     
carl       9     
mark       11     
bob        10     
neil       1     
louis      14     
所以,我想要的是完成原始查询,并用一个查询在其中一个查询之前和之后获取记录。。。让我们说“卡尔”,但重要的是,在每种情况下都是不同的,我的意思是,其他时间需要在“鲍勃”之前和之后


那么,让我们说“卡尔”。。。我只需要创建一个SQL查询,在该查询中,我使用所描述的order by字段,并在字段\u a='carl'

时获取前后行。您可以使用一个查询,但需要在两个集合之间合并以将结果合并在一起

SELECT * FROM
(
SELECT b.*
from tbl a
inner join tbl b on
      b.field_m = '100'
  and b.field_n = '200'
where a.field_m = '100'
  and a.field_n = '200'
  and a.field_a = 'carl'
  and b.field_x <= a.field_x  # comes before a sorted on x
order by b.field_x DESC
limit 2
) A
UNION
SELECT * FROM
(
SELECT b.*
from tbl a
inner join tbl b on
      b.field_m = '100'
  and b.field_n = '200'
where a.field_m = '100'
  and a.field_n = '200'
  and a.field_a = 'carl'
  and b.field_x >= a.field_x  # comes after a sorted on x
order by b.field_x ASC
limit 2
) B

其工作方式是将集合交叉到自身,其中a定位在“carl”处,b仅保留位置上位于集合1之前或之后的行。正确地排序这些表,然后使用
限制2
将包括“carl”和另一个(除非在允许重复的情况下,这也是“carl”)

这对大表来说是相当沉重的,但是您可以使用排名和两次连接来获得上一个和下一个记录,然后只使用where来过滤它

SET @rank_prev = 0;
SET @rank_cur = 0; 
SET @rank_next = 0;
SELECT
    prev.field_a as prev_a,
    prev.field_b as prev_b,
    next.field_a as next_a,
    next.field_b as next_b
FROM
 (  
  SELECT
      @rank_cur:=@rank_cur+1 AS rank,
      field_a, 
      field_b  
  FROM dd
  WHERE field_m = '100' 
    AND field_n = '200'
  ORDER BY field_x
 ) as cur
INNER JOIN
 (
  SELECT
      @rank_prev:=@rank_prev+1 AS rank,
      field_a, 
      field_b  
  FROM dd
  WHERE field_m = '100' 
    AND field_n = '200'
  ORDER BY field_x
 ) as prev
 ON prev.rank + 1 = cur.rank
INNER JOIN
 (
  SELECT
      @rank_next:=@rank_next+1 AS rank,
      field_a, 
      field_b  
  FROM dd
  WHERE field_m = '100' 
    AND field_n = '200'
  ORDER BY field_x
 ) as next
 ON cur.rank+1 = next.rank
 WHERE cur.field_a = 'carl';

在MySQL上工作

嗨,你认为在一个有2000.000条记录的表中这会很快吗?如果你有一个复合索引(field_m,field_n,field_x),它会很好,每个分支只看一条记录对不起,但是那些子查询会返回“where field_m='100'和field_n='200'”记录集的第一行和第二行。。。不是我一直在测试的“carl”行的前后,这将与表上的自动递增ID字段一起工作。。。事实并非如此。。。“field_xfield_x一无所知-它只是对记录进行排序!那么如何检查
字段x
?您以前必须使用排名来查找carl的位置,但这不是一次性查询。您好,您认为在一个有2000.000条记录的表中这样做会很快吗?顺便说一下,我认为缺少连接:P@user311188我说它会在大桌子上很沉@user311188您是对的,连接丢失了,因为它不应该是交叉连接,而是内部连接。回答已更正。@user311188当然通过临时表执行此操作会快得多-选择进入表,排列记录(或在临时表中使用自动递增),查找carl的记录并输出上一个和下一个(秩-1,秩+1)。但您提出了一个一次性解决方案:)
SET @rank_prev = 0;
SET @rank_cur = 0; 
SET @rank_next = 0;
SELECT
    prev.field_a as prev_a,
    prev.field_b as prev_b,
    next.field_a as next_a,
    next.field_b as next_b
FROM
 (  
  SELECT
      @rank_cur:=@rank_cur+1 AS rank,
      field_a, 
      field_b  
  FROM dd
  WHERE field_m = '100' 
    AND field_n = '200'
  ORDER BY field_x
 ) as cur
INNER JOIN
 (
  SELECT
      @rank_prev:=@rank_prev+1 AS rank,
      field_a, 
      field_b  
  FROM dd
  WHERE field_m = '100' 
    AND field_n = '200'
  ORDER BY field_x
 ) as prev
 ON prev.rank + 1 = cur.rank
INNER JOIN
 (
  SELECT
      @rank_next:=@rank_next+1 AS rank,
      field_a, 
      field_b  
  FROM dd
  WHERE field_m = '100' 
    AND field_n = '200'
  ORDER BY field_x
 ) as next
 ON cur.rank+1 = next.rank
 WHERE cur.field_a = 'carl';