我在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'
时采用前后行答案 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')。