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

时间:2011-01-25 23:03:09

标签: 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     
marty      7     
peter      2     
carl       9     
mark       11     
bob        10     
neil       1     
louis      14     

所以,我想要的是完成原始查询并使用ONE QUERY在其中一个之前和之后记录...让我们说“carl”,但重要的是,在每种情况下都不同,我的意思是,其他时间需要在“bob”之前和之后......

所以,让我们说“carl”...我需要创建一个只有SQL QUERY,其中我使用了描述的field_x的顺序,并在field_a ='carl'

时采用前后行

2 个答案:

答案 0 :(得分: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';

适用于MySQL

答案 1 :(得分:0)

您可以使用一个查询,但需要两个集合之间的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 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

注意:这包括'carl'本身。 UNION负责移除第二个'carl'。

性能 - 应至少在(field_m, field_n)创建一个索引,如果(field_m, field_n, field_x)更好,则可以合理地执行此查询。只要field_m + field_n将表格缩小到最大尺寸,性能就是

(size after filter m/n) x (size after filter m/n)  // triangular
x2

这种方式的工作方式是它与自身交叉的集合,其中a锚定在“carl”,而b仅保留位置之前(设置1)或之后(设置)的行2)。正确排序然后取LIMIT 2将包括'carl'以及另外一个(除非在允许重复时也是'carl')。